Prev: "PORTING C" > Non inclusion of header = no errors ?
Next: 'this' parameter in virtual function calls
From: Larry on 28 Dec 2009 20:16 Hi, I am still stuck at programming with the waveForm API on windows. Actually, I managed to write some code to record the audio from the mic real time. Yet, I'd like to use more then one buffer to do it in order to avoid choppy recording. In a nutshell, I should pass the waveInPrepareHeader and waveInAddBuffer more then one single buffer, something like this: [code] // Define WAVEHDR Structure: WAVEHDR *buff = new WAVEHDR[num_buffers]; for (int i = 0; i<num_buffers; i++) { buff[i].lpData = (LPSTR) malloc(system_buf_len); buff[i].dwBufferLength = system_buf_len; buff[i].dwBytesRecorded = 0; buff[i].dwUser = 0; buff[i].dwFlags = 0; buff[i].dwLoops = 0; if(waveInPrepareHeader(hwi, &buff[i], sizeof(WAVEHDR)) != MMSYSERR_NOERROR) printf("waveInPrepareHedare: ERROR!\n"); // return -1; if(waveInAddBuffer(hwi, &buff[i], sizeof(WAVEHDR)) != MMSYSERR_NOERROR) printf("waveInAddBuffer: ERROR!\n"); // return -1; } if(waveInStart(hwi) != MMSYSERR_NOERROR) printf("waveInStart: ERROR!\n"); // return -1; [/code] The system sends me messages about the filling of a buffer by using a CALLBACK_EVENT, so I have to wait for it with WaitForSingleObject() function. Now, I am stuck at guessing how to capture the single filled buffer from the array of buffers...I tried something like this: [code] // Loop... while(1) { if(stop_thread_flag) break; // CALLBACK EVENT WaitForSingleObject(hevent, INFINITE); for (int k = 0; k<num_buffers; k++) { if(buff[k].dwFlags & WHDR_DONE) { save_buffer(&buff[k]); waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR)); } } } for (int u = 0; u<num_buffers; u++) { waveInUnprepareHeader(hwi, &buff[u], sizeof(WAVEHDR)); } waveInClose(hwi); return 0; [/code] Although it seems to be working, I am not sure wheter it is the right way to deal with that. Do you think I shoud add a "last" after I check for the flags to be WHDR_DONE? How can I make sure I am not getting the same single buffer twice or more? The whole code is avaible here: http://theartofweb.net/cpp/waveform_recorder_05.txt thanks
From: Tim Roberts on 29 Dec 2009 01:21 "Larry" <dontmewithme(a)got.it> wrote: > > I am still stuck at programming with the waveForm API on windows. >Actually, I managed to write some code to record the audio from the mic real >time. Yet, I'd like to use more then one buffer to do it in order to avoid >choppy recording. >... > // CALLBACK EVENT > WaitForSingleObject(hevent, INFINITE); > for (int k = 0; k<num_buffers; k++) > { > if(buff[k].dwFlags & WHDR_DONE) > { > save_buffer(&buff[k]); > waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR)); > } > } > } > for (int u = 0; u<num_buffers; u++) > { > waveInUnprepareHeader(hwi, &buff[u], sizeof(WAVEHDR)); > } > waveInClose(hwi); > return 0; >[/code] > >Although it seems to be working, I am not sure wheter it is the right way to >deal with that. Do you think I shoud add a "last" after I check for the >flags to be WHDR_DONE? How can I make sure I am not getting the same single >buffer twice or more? This is basically the right idea. If it were me, I would clear the WHDR_DONE flag in the header as soon as I saw it was set, to avoid the duplicate buffer problem. I suspect that waveInAddBuffer will do that for you, but no harm in being safe. The only other problem has to do with wraparound. If there were a delay such that two buffers completed before you got around to enumerating the list, you might get a case where the very last and the very first buffer were the ones filled. Your code, because it starts at 0 each time, would get them in the wrong order. The way I would solve that is to use a std::list to hold the headers. Pop the finished ones off the top, push empty ones back in the bottom. -- Tim Roberts, timr(a)probo.com Providenza & Boekelheide, Inc.
From: Larry on 29 Dec 2009 07:10 "Tim Roberts" <timr(a)probo.com> ha scritto nel messaggio news:1f7jj5h0jtomiss0b3ajc9qjpbabsk6ate(a)4ax.com... > This is basically the right idea. If it were me, I would clear the > WHDR_DONE flag in the header as soon as I saw it was set, to avoid the > duplicate buffer problem. I suspect that waveInAddBuffer will do that for > you, but no harm in being safe. I am sure the waveInAddBuffer is doing that for me. > The only other problem has to do with wraparound. If there were a delay > such that two buffers completed before you got around to enumerating the > list, you might get a case where the very last and the very first buffer > were the ones filled. Your code, because it starts at 0 each time, would > get them in the wrong order. The way I would solve that is to use a > std::list to hold the headers. Pop the finished ones off the top, push > empty ones back in the bottom. Ok this is how I push the buffers to the waveIn functions before actually staring recording: // WAVEHDR *buff = new WAVEHDR[num_buffers]; for (int i = 0; i<num_buffers; i++) { buff[i].lpData = (LPSTR) malloc(system_buf_len); buff[i].dwBufferLength = system_buf_len; buff[i].dwBytesRecorded = 0; buff[i].dwFlags = 0; waveInPrepareHeader(hwi, &buff[i], sizeof(WAVEHDR)); waveInAddBuffer(hwi, &buff[i], sizeof(WAVEHDR)); } waveInStart(hwi); // So, if I set up 3 buffers I'll have: buff[0], buff[1], buff[2] pushed in the waveInPrepareHeader() and waveInAddBuffer() in that order. Now, I am almost sure I should get the buffers from the system in that order as well, so I came up with something like this: // Loop... int k = 0; while(1) { // CALLBACK EVENT WaitForSingleObject(hevent, INFINITE); if(buff[k].dwFlags & WHDR_DONE) { save_buffer(&buff[k]); waveInAddBuffer(hwi, &buff[k], sizeof(WAVEHDR)); } if(k == num_buffers -1) k = 0; else k++; } for (int u = 0; u<num_buffers; u++) { waveInUnprepareHeader(hwi, &buff[u], sizeof(WAVEHDR)); } waveInClose(hwi); // I guess this time I got it right! I get the buff[0] then I push it again to the waveInAddBuffer() and so forth...what do you think about it? thanks
From: Tim Roberts on 30 Dec 2009 23:11 "Larry" <dontmewithme(a)got.it> wrote: > >I guess this time I got it right! I get the buff[0] then I push it again to >the waveInAddBuffer() and so forth...what do you think about it? This looks pretty much right to me. Does it work? -- Tim Roberts, timr(a)probo.com Providenza & Boekelheide, Inc.
From: Larry on 31 Dec 2009 04:45
"Tim Roberts" <timr(a)probo.com> ha scritto nel messaggio news:i39oj5tfsfvcmo5ql1geusho7oq5p9dm8r(a)4ax.com... > This looks pretty much right to me. Does it work? Yes it is!!!! |