-
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.
-
You should post the relevant code, nobody is going to read your whole code!
-
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));
}
-
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.
-
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.
-
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.