Audio Microcontroller Recommendation

Status
Not open for further replies.

leonidas25

New Member
Hello! I have some basic knowledge with microprocessors and I want to increase my knowledge. I've been having problems finding a microcontroller that could help me. This is the project I need to do:

I need to receive an audio signal. Convert it to digital. Process it and then convert it again to analog and transmit it as output audio signal with a different volume according to a test done while processing.
Let me explain: While the audio data is being processed it should be able to detect silence, immediately a beep is transmitted at a certain volume and the person listening need to push a button/switch. If the person fails to do this, it means they couldn't hear the beep and the volume must be decreased​

I know I need a micro with ADC & DAC embedded. I know PWD might help. Do I need amps for the phone jacks? I also know I need a microcontroller with an audio codec embedded to make it easier (I still have problems understanding this audio codec thing, is it a code, is it a component?)

Hope I can find some help in this forum, thanks in advance for your attention!
 
Thanks so much Nigel & Gayan!
I will try your suggestions and post back!

Any other suggestions from other members??
 
Extra Help

I need more help please.
I have a lot of questions and I don't really know how much you are allowed to tell me, or probably my questions are just very basic. Please at least guide me in the right direction

I opted for the PGA2311. This is what I understand about it. It is basically a volume controller that needs something that drives it (am I correct?)

If I am correct then, because I already have a PIC18LF2520 I want to use this PIC to control it. But here is where I am getting very confused

How will the PGA detect the silence? I am guessing it doesn't detect silence (It will be in someway the PIC18 right?) Now, do I need feedback to detect it? Let's say it is detected, how am I going to send a beep to the PGA? can I connect 2 different audio inputs to a single PGA2311??

Something else and I am afraid this is very basic, can I just plug in the audio input to the PGA2311? do I need an amplifier? I was checking the datasheet and apparently I don't need anything else, just want to make sure

Thanks for taking the time to understand my questions. Hope you can help me out!
 
It's just a volume control IC, that's all it does - which was why I suggested a dsPIC - you could use the dsPIC as well as the volume control IC, but it seems a bit pointless using the volume control IC?.
 
was that sarcasm? I really appreciate your fast response. Could you guide me to a tutorial webpage or manual for dsPIC. I'm thinking I will better use it now that I realized everything could be together on it
 
was that sarcasm? I really appreciate your fast response. Could you guide me to a tutorial webpage or manual for dsPIC. I'm thinking I will better use it now that I realized everything could be together on it

I've never used one, but apparently there are a number of examples for different DSP applications on the MicroChip website.
 
Get a dsPIC, start programming to blink a LED, then enable ADC with constant analog voltage, then take in audio signal and process in the program.
Use MPLAB C30 C compiler from Microchip.
The attached are the datasheets I used last few years for audio related project.
 

Attachments

  • dsPIC33FJ12GP201 202.pdf
    3.5 MB · Views: 222
  • 70183A Analog-to-Digital Converter (ADC).pdf
    934.2 KB · Views: 262
  • AN699 Anti-Aliasing, Analog Filters for Data Acquisition Systems.pdf
    171.6 KB · Views: 356
I use dsPIC fairly extensively.

The dsPIC has an ADC and DAC. However, the ADC is somewhat limited for audio use because of its bit depth and often needs signal conditioning hardware. The DAC needs an amplifier. Codec chips with signal conditioning (PGA, AC-coupling, appropriate input filtering), 16-bit 22KHz "full quality" audio, and a DAC capable of driving headphones or even a speaker are not expensive. A codec can be cheaper than buying the external parts, and less trouble. The dsPIC can talk to a codec easily with the DCI or even the SPI port.

Si3000 has been a well-used codec for VOICE range on the dsPIC (<4KHz). It can't input nor output a higher freq.

The dsPIC is a really good core. It has peripherals and runs assembly instructions like any other controller, there's also a C-compiler, but it's a handy 16-bit core. But it also has several critical DSP-core features, like a pair of 40-bit Accumulators and the MAC (Multiply and Accumulate) instruction, with dual preload, which makes implementing digital filters MUCH more efficient. Even with a 16-bit core,a 16-bit FIR takes a LOT more instructions without the DSP features.

In fact if you're just writing a normal program, the series is great! There's 16 Working registers, NO memory paging, a hardware stack with stack frames, error interrupts, DMA (on the 33F), and a much more powerful instruction set. But if you don't need the DSP core, the 24F series IS the same thing but cheaper/no DSP core.

The 30F series is the same core as the 3.3v 33F, but 5v (or 3.3v at reduced max speed), no DMA, and it takes a LOT of power at higher speeds, and can't go as fast as a 33F. In fact a 30F in a smaller package can easily overheat at top speed at 5v without a heatsink.
 
Last edited:
wow, thanks so much!! bananaslong & Oznog
this was the help I needed. I greatly appreciate your help. I will begin to play with the dsPIC

I'll let you guys know my progress
 
Still need a little more help

First of all, thanks again for the support. I've been playing around with the "dsPIC Starter Kit" I want to refer to the following webpage:

**broken link removed**

this is where I have my questions refering to one of the demo files "SASK WM8510 Record Play Demo With Intro". Basically what this demo does is to constantly play some instructions, then if you press SW1, you'll be able to record 1 minute of audio, then it will be played in a constant loop. I kinda understand how it works because I also read the PDF included.

I modified the main.c code to disable the saving to memory and just play what is coming in real-time (could I say streaming?)

I need some more guidance to be able to detect a silence between songs, increase or decrease the volume, and also recreate a "beep" sound (all this related to my very first post)

I am posting the code I modified (actually, just commented what wasn't needed), could someone help me out with some code I can add or any kind of tutorial for the dsPIC kit? I couldn't follow that much the code, what can I read to understand it better? thanks a lot!

main.c
Code:
/**********************************************************************

* © 2007 Microchip Technology Inc.

*

* FileName:        main.c

* Dependencies:    Header (.h) files if applicable, see below

* Processor:       dsPIC33FJ256GP506

* Compiler:        MPLAB® C30 v3.00 or higher

*

************************************************************************/



#include <p33FJ256GP506.h>

#include "..\h\WM8510CodecDrv.h"

#include "..\h\sask.h"

#include "..\h\AT25F4096Drv.h"

#include "..\h\G711.h"





_FGS(GWRP_OFF & GCP_OFF);

_FOSCSEL(FNOSC_FRC);

_FOSC(FCKSM_CSECMD & OSCIOFNC_ON & POSCMD_NONE);

_FWDT(FWDTEN_OFF);



//#define FRAME_SIZE 				128			/* Each audio frame will have these many samples	*/

#define FRAME_SIZE 				320			/* Each audio frame will have these many samples	*/

#define SPEECH_SEGMENT_SIZE		98049L		/* Length of the intro message						*/

#define WRITE_START_ADDRESS		0x20000		/* Flash memory address for user					*/





/* Allocate memory for buffers and drivers	*/



int 	codecBuffer			[WM8510DRV_DRV_BUFFER_SIZE];

int 	samples				[FRAME_SIZE];

char 	encodedSamples		[FRAME_SIZE];

int 	decodedSamples		[FRAME_SIZE];

char 	flashMemoryBuffer	[AT25F4096DRV_BUFFER_SIZE];



/* Instantiate the drivers 	*/

WM8510Handle codec;

AT25F4096Handle flashMemoryHandle; 



/* Create the driver handles	*/

WM8510Handle * codecHandle = &codec;

AT25F4096Handle *pFlashMemoryHandle 	= &flashMemoryHandle;





 long currentReadAddress;		/* This one tracks the intro message	*/

 long currentWriteAddress;		/* This one tracks the writes to flash	*/

 long userPlaybackAddress;		/* This one tracks user playback		*/



int record;						/* If set means recording				*/

int playback;					/* If set means playback is in progress	*/

int erasedBeforeRecord;			/* If set means that erase before record*/

								/* is complete							*/ 

long address;					/* Used for erasing the flash			*/





int main(void)

{

	/* Configure Oscillator to operate the device at 40MHz.

	 * Fosc= Fin*M/(N1*N2), Fcy=Fosc/2

	 * Fosc= 7.37M*40/(2*2)=80Mhz for 7.37M input clock */

 

	PLLFBD=41;				/* M=39	*/

	CLKDIVbits.PLLPOST=0;	/* N1=2	*/

	CLKDIVbits.PLLPRE=0;	/* N2=2	*/

	OSCTUN=0;			

	

	__builtin_write_OSCCONH(0x01);		/*	Initiate Clock Switch to FRC with PLL*/

	__builtin_write_OSCCONL(0x01);

	while (OSCCONbits.COSC != 0b01);	/*	Wait for Clock switch to occur	*/

	while(!OSCCONbits.LOCK);



	/* Initialize flags and address variables	*/

	 record = 0;

	 playback = 0;

	 currentReadAddress = 0;

	 currentWriteAddress = WRITE_START_ADDRESS;

	 userPlaybackAddress = WRITE_START_ADDRESS;

	 address = 0;

	 erasedBeforeRecord = 0;	





	/* Intialize the board and the drivers	*/

	SASKInit();

	WM8510Init(codecHandle,codecBuffer);

	AT25F4096Init		(pFlashMemoryHandle,flashMemoryBuffer);	/* For the  Flash	*/



	/* Start the flash driver functions	*/

	

	AT25F4096Start	(pFlashMemoryHandle);

		

	/* Start Audio input and output function	*/

	WM8510Start(codecHandle);

		

	/* Configure codec for 8K operation	*/

	WM8510SampleRate8KConfig(codecHandle);



	/* Main processing loop. Executed for every input and 

	 * output frame	*/

	 

	while(1)

	{

			/* Obtaing the ADC samples	*/

			while(WM8510IsReadBusy(codecHandle));

			WM8510Read(codecHandle,samples,FRAME_SIZE);

					

//			/* Playback the intro message if record or play functions are not active	

//			 * Rewind the currentReadAddress if the message has reached the end	*/

//			if(!record && !playback)

//			{	

//				while(AT25F4096IsBusy(pFlashMemoryHandle));

//				AT25F4096Read(pFlashMemoryHandle,currentReadAddress,encodedSamples,FRAME_SIZE);

//				while(AT25F4096IsBusy(pFlashMemoryHandle));

//				currentReadAddress += FRAME_SIZE;

//				if(currentReadAddress >= SPEECH_SEGMENT_SIZE)

//				{

//					currentReadAddress = 0;

//				}

//			}

			

			/* If record is enabled, encode the samples using G711. 

			 * Store in flash. Erase flash before recording starts	*/

			 	

			if(record == 1)

			{

//			

//				if(erasedBeforeRecord == 0)

//				{

//					/* Stop the Audio input and output since this is a blocking

//					 * operation. Also rewind record and playback pointers to

//					 * start of the user flash area.*/

//					 

//					WM8510Stop(codecHandle);

//					currentWriteAddress = WRITE_START_ADDRESS;

//					userPlaybackAddress = WRITE_START_ADDRESS;

//					RED_LED = SASK_LED_ON;

//					YELLOW_LED = SASK_LED_OFF;

//				

//					/* Erase the user area of the flash. The intro message is not erased	*/

//					for(address = WRITE_START_ADDRESS; address < AT25F4096DRV_LAST_ADDRESS; address += 0x10000)

//					{

//						/* Erase each sector. Each sector is 0xFFFF long	*/

//						AT25F4096IoCtl(pFlashMemoryHandle,AT25F4096DRV_WRITE_ENABLE,0);	

//						AT25F4096IoCtl(pFlashMemoryHandle,AT25F4096DRV_SECTOR_ERASE,(void *)&address);	

//						while(AT25F4096IsBusy(pFlashMemoryHandle));

//					}

//					RED_LED = SASK_LED_OFF;

//					

//					/* Since erase is complete, the next time the loop is executed

//					 * dont erase the flash. Start the audio input and output	*/

//					 

//					erasedBeforeRecord = 1;

//					WM8510Start(codecHandle);

//				}

//				else

//				{	

//					/* Record the encoded audio frame. Yellow LED turns on when

//					 * when recording is being performed	*/

//					

					YELLOW_LED = SASK_LED_ON;

					G711Lin2Ulaw(samples,encodedSamples,FRAME_SIZE);	// HR: Turns on the buffering

				

//					while(AT25F4096IsBusy(pFlashMemoryHandle));

//					AT25F4096IoCtl(pFlashMemoryHandle,AT25F4096DRV_WRITE_ENABLE,0);

//					AT25F4096Write(pFlashMemoryHandle,currentWriteAddress,encodedSamples,FRAME_SIZE);

//					currentWriteAddress += FRAME_SIZE;

//				

//					if(currentWriteAddress >= AT25F4096DRV_LAST_ADDRESS)

//					{

//					

//						YELLOW_LED = SASK_LED_OFF;

//						erasedBeforeRecord = 0;

//						record = 0;

//						playback = 1;

//					}

//				}

//					

			}

			

			/* If playback is enabled, then start playing back samples from the

			 * user area. Playback only till the last record address and then 

			 * rewind to the start	*/

			 

//			if(playback == 1)

//			{

//				GREEN_LED = SASK_LED_ON;

//				erasedBeforeRecord = 0;		

//				while(AT25F4096IsBusy(pFlashMemoryHandle));				

//				AT25F4096Read(pFlashMemoryHandle,userPlaybackAddress,encodedSamples,FRAME_SIZE);

//				while(AT25F4096IsBusy(pFlashMemoryHandle));

//			

//				userPlaybackAddress += FRAME_SIZE;

//				

//				if(userPlaybackAddress >= currentWriteAddress)

//				{

//					userPlaybackAddress = WRITE_START_ADDRESS;

//				}

//			}

//				

//		

//				

//		

			/* Decode the samples	*/

			G711Ulaw2Lin (encodedSamples,decodedSamples, FRAME_SIZE);

	

			/* Wait till the codec is available for a new  frame	*/

//			while(WM8510IsWriteBusy(codecHandle));	// HR: Aparrently not needed

		

			/* Write the frame to the output	*/

			WM8510Write (codecHandle,decodedSamples,FRAME_SIZE);

		

			

			/* The CheckSwitch functions are defined in sask.c	*/

			

			if((CheckSwitchS1()) == 1)

			{

				/* Toggle the record function and Yellow led.

				 * Rewind the intro message playback pointer. 

				 * And if recording, disable playback.*/

				 

				

				record =1;	// HR: Important to enable the "if" above			

//				currentReadAddress = 0;	

//				erasedBeforeRecord = 0;

				if(record == 1)

				{

//					playback = 0;

					GREEN_LED = SASK_LED_OFF;



//				}

//				else

//				{

					YELLOW_LED = SASK_LED_OFF;

				}

			}

			

			

			if((CheckSwitchS2()) == 1)

			{

				/* Toggle the record function and AMBER led.

				 * Rewind the intro message playback pointer. 

				 * And if recording, disable playback.*/

				 

				GREEN_LED ^=1;

//				playback =1 ;

//				userPlaybackAddress = WRITE_START_ADDRESS;

//				currentReadAddress = 0;		

//				if(playback == 1)

//				{

//					record = 0;

					YELLOW_LED = SASK_LED_OFF;

//				}

			}

			

			

	

	}

	

	

}
 
Detect silence? Well, I'd say the RMS value of past samples... but there is no single accepted criteria for "silence". It is likely that transient noise might need to be avoided, so you'd want to look for an average over the past 0.1 sec, 1 sec, etc being over a certain threshold. You might want to filter out high or low pitches that aren't in the desired range. You might filter transient noise by saying "ok, consider the RMS value over the last 10x 0.1 sec periods- if ANY 0.1 sec period has an RMS value under 6, then it's transient noise, not the sound I'm looking for."

In some cases you may want to retroactively decide what "silence" is. Like some music tracks contain dead spots as part of the song, but none are like 3 sec long, right? Well, do we let 3 sec go by before declaring "end of track"? Or do we buffer 3 sec of audio, and if we see 3 sec of silence, go back in the buffer to 3 sec ago and declare that end-of-track?

Increasing or decreasing volume can be done in the codec chip, or you can do it in software with Fractional Multiply.
 
Last edited:
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…