Thread: voice echo

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    8

    voice echo

    I was trying to write a program that waits for 10 seconds for voice input from the mic ,and then echoes it back.
    The problem is that when playing back the recorded data , it is played so slowly that it is impossible to recognize...
    I know that the recording part is OK , because when trying to playback without any buffering scheme using some code I found on the net the playback worked just fine , so probably it's me doing something wrong.

    I attached three files :
    sound.h which includes mostly structs for the SoundOut.c file.
    SoundOut.c which deals with the play back.
    main.c includes most of the recording code and uses SoundOut.c to playback.
    note that the second option for playback [without any buffering scheme] is commented , and when I use it everything works just fine.

    please reply even if you only got an idea about what can be wrong , because I'm out of ideas.

    realcr.

    PS (EDIT) - If anyone have ever seen a working example that does something related to what I'm trying to do please point me to that example if you can. It is really difficult to find any example of C sound API on the net.
    Last edited by realcr; 04-18-2006 at 04:31 PM. Reason: addition

  2. #2
    C / C++
    Join Date
    Jan 2006
    Location
    The Netherlands
    Posts
    312
    You should post the relevant code, nobody is going to read your whole code!
    Operating Systems:
    - Ubuntu 9.04
    - XP

    Compiler: gcc

  3. #3
    Registered User
    Join Date
    Mar 2006
    Posts
    8
    U are right , however I still don't know what is the relevant part of code. Maybe these parts:


    Code:
    int main(int argc, char *argv[])
    {
         const int NUMPTS = 44100 * 10;   // 10 seconds
         int sampleRate = 44100;
         short int waveIn[NUMPTS];   // 'short int' is a 16-bit type; I request 16-bit samples below
                                     // for 8-bit capture, you'd use 'unsigned char' or 'BYTE' 8-bit types
        
         HWAVEIN      hWaveIn;
         WAVEHDR      WaveInHdr;
         MMRESULT     result;
        
         memset(waveIn,0,NUMPTS);
         // Specify recording parameters
         WAVEFORMATEX pFormat;
         pFormat.wFormatTag=WAVE_FORMAT_PCM;     // simple, uncompressed format
         pFormat.nChannels=1;                    //  1=mono, 2=stereo
         pFormat.nSamplesPerSec=sampleRate;      // 44100
         pFormat.nAvgBytesPerSec=sampleRate*2;   // = nSamplesPerSec * n.Channels * wBitsPerSample/8
         pFormat.nBlockAlign=2;                  // = n.Channels * wBitsPerSample/8
         pFormat.wBitsPerSample=16;              //  16 for high quality, 8 for telephone-grade
         pFormat.cbSize=0;
        
         result = waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat,
                    0L, 0L, WAVE_FORMAT_DIRECT);


    Code:
    void SoundOutWrite(soundOut* so, char* data, int size)
    {
        WAVEHDR* current;
        int written = 0;
        int i;
        
        
        while(size > 0) 
        {
             
            while(so->freeBuff <= 0) //go on only if we have some free buffers.
                Sleep(100);
            //note for the disbelievers : usually we got much more than one free buffer,
            //so I put this busy waiting here just in case.
            //I couldn't use semaphores or Critical section because of some reasons related
            //to this case.
            current = &(so->buffers[so->firstBuff].header); //current header.
            //first make sure the header we're going to use is unprepared
            if(current->dwFlags & WHDR_PREPARED)
            { 
                waveOutUnprepareHeader(so->hWaveOut, current, sizeof(WAVEHDR));
                //I don't actually know yet why can we unprepare stuff at the callback function.
                //there is probably some reason for that.
            }
            
            if(size > SOUND_BUFFER_SIZE)
            {
                  
                  memcpy(current->lpData,(char*)(data+written),SOUND_BUFFER_SIZE);
                  
                  size-=SOUND_BUFFER_SIZE;
                  written+=SOUND_BUFFER_SIZE;
                  current->dwBufferLength = SOUND_BUFFER_SIZE;
                 
            }
            else
            {
                  
                  memset(current->lpData,0,SOUND_BUFFER_SIZE); //TODO: check
                  memcpy(current->lpData,(char*)(data+written),size);
                  written+=size;
                  size = 0;
                  current->dwBufferLength = size;
            }
            
            EnterCriticalSection(&(so->freeSection));
            so->freeBuff--;
            LeaveCriticalSection(&(so->freeSection));
    
            so->firstBuff = (so->firstBuff+1)%SOUND_BUFFERS;
    
            waveOutPrepareHeader(so->hWaveOut, current, sizeof(WAVEHDR));
            waveOutWrite(so->hWaveOut, current, sizeof(WAVEHDR));
                                                     
            
            
    
            
        }
    Code:
    //the callback function.
    void CALLBACK SoundOutProc(
    HWAVEOUT hWaveOut, 
    UINT uMsg, 
    DWORD dwInstance, 
    DWORD dwParam1,
    DWORD dwParam2 
    )
    
    
    {
        //printf("I wuz hear\n");
        if(uMsg != WOM_DONE) //ignore calls that occur due to opening and closing the device.
                return;
        //pointer to the soundOut struct.
        soundOut* so = (soundOut*)dwInstance;
        
        
        so->lastBuff = (so->lastBuff+1)%SOUND_BUFFERS;
        EnterCriticalSection(&(so->freeSection));
        so->freeBuff++; //we got another free buffer.
        LeaveCriticalSection(&(so->freeSection));
        
    }

  4. #4
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I only scanned your code, but I noticed a couple of things:

    - For the buffered code, you use a different size to the unbuffered code:
    Code:
         SoundOutWrite(&so,(char*)waveIn,NUMPTS*2);
    
       ...
    
        header.dwBufferLength = NUMPTS;
    - When you are expecting callback functions from the wave API, I think you need to pump the message loop. You should try running a message loop after calling SoundOutWrite.

  5. #5
    Registered User
    Join Date
    Mar 2006
    Posts
    8
    Thanks mouse,
    indeed there seems to be something is wrong in my code with the size of buffers. I will check it out and return with answer and fixed code.

    realcr.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    8
    I found out that when I increase the size of the buffer , the playback is better , however there are still jumps in the middle (they just occur less often).

    realcr.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Batch file programming
    By year2038bug in forum Tech Board
    Replies: 10
    Last Post: 09-05-2005, 03:30 PM
  2. A breakthrough
    By loopy in forum Linux Programming
    Replies: 4
    Last Post: 11-26-2003, 06:46 PM
  3. C-Shell Scripting.. Help!
    By denizengt in forum Tech Board
    Replies: 3
    Last Post: 10-29-2003, 01:37 PM
  4. voice technologies
    By Dissata in forum A Brief History of Cprogramming.com
    Replies: 6
    Last Post: 01-04-2002, 04:22 AM
  5. echo command
    By Billing in forum A Brief History of Cprogramming.com
    Replies: 2
    Last Post: 08-31-2001, 08:38 PM