ReactOS 0.4.15-dev-7918-g2a2556c
audio_wavein.cpp
Go to the documentation of this file.
1/* PROJECT: ReactOS sndrec32
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/sndrec32/audio_wavein.cpp
4 * PURPOSE: Sound recording
5 * PROGRAMMERS: Marco Pagliaricci (irc: rendar)
6 */
7
8#include "stdafx.h"
9#include "audio_wavein.hpp"
10
12
13void
15{
18 wavein_handle = 0;
19 recthread_id = 0;
24}
25
26void
27audio_wavein::alloc_buffers_mem_(unsigned int buffs, float secs)
28{
29 unsigned int onebuf_size = 0, tot_size = 0;
30
31 /* Release old memory */
32 if (main_buffer)
33 delete[] main_buffer;
34
35 if (wave_headers)
36 delete[] wave_headers;
37
38 /* Calcs size of the buffers */
39 onebuf_size = (unsigned int)((float)aud_info.byte_rate() * secs);
40 tot_size = onebuf_size * buffs;
41
42 /* Allocs memory for the audio buffers */
43 main_buffer = new BYTE[tot_size];
44 /* Allocs memory for the `WAVEHDR' structures */
45 wave_headers = (WAVEHDR *)new BYTE[sizeof(WAVEHDR) * buffs];
46 /* Zeros memory */
47 ZeroMemory(main_buffer, tot_size);
48 ZeroMemory(wave_headers, sizeof(WAVEHDR) * buffs);
49 /* Updates total size of the buffers */
50 mb_size = tot_size;
51}
52
53void
55{
56 /* Frees memory */
57 if (main_buffer)
58 delete[] main_buffer;
59
60
61 if (wave_headers)
62 delete[] wave_headers;
63
64 main_buffer = 0;
65 wave_headers = 0;
66}
67
68void
70{
71 /* If there is no memory for memory or headers, simply return */
72 if ((!wave_headers) || (!main_buffer))
73 return;
74
75 /* This is the size for one buffer */
76 DWORD buf_sz = mb_size / buffers;
77 /* This is the base address for one buffer */
78 BYTE *buf_addr = main_buffer;
79 /* Initializes headers */
80 for (unsigned int i = 0; i < buffers; ++i)
81 {
83 wave_headers[i].lpData = (LPSTR)buf_addr;
84 buf_addr += buf_sz;
85 }
86}
87
88void
90{
92 bool error = false;
93
94 /* If there is no memory for memory or headers, throw error */
95 if ((!wave_headers) || (!main_buffer) || (!wavein_handle))
96 {
97 /* TODO: throw error! */
98 }
99
100 for (unsigned int i = 0; i < buffers; ++i)
101 {
103 if (err != MMSYSERR_NOERROR)
104 error = true;
105 }
106
107 if (error)
108 MessageBox(0, TEXT("waveInPrepareHeader Error."), 0, 0);
109}
110
111void
113{
115 bool error = false;
116
117 /* If there is no memory for memory or headers, throw error */
118 if ((!wave_headers) || (!main_buffer) || (!wavein_handle))
119 {
120 /* TODO: throw error! */
121 }
122
123 for (unsigned int i = 0; i < buffers; ++i)
124 {
126 if (err != MMSYSERR_NOERROR)
127 error = true;
128 }
129
130 if (error)
131 MessageBox(0, TEXT("waveInUnPrepareHeader Error."), 0, 0);
132}
133
134void
136{
138 bool error = false;
139
140 /* If there is no memory for memory or headers, throw error */
141 if ((!wave_headers) || (!main_buffer) || (!wavein_handle))
142 {
143 /* TODO: throw error! */
144 }
145
146 for (unsigned int i = 0; i < buffers; ++i)
147 {
149 if (err != MMSYSERR_NOERROR)
150 error = true;
151 }
152
153 if (error)
154 MessageBox(0, TEXT("waveInAddBuffer Error."), 0, 0);
155}
156
157void
159{
160 /* If wavein object is already in the status NOTREADY, nothing to do */
161 if (status == WAVEIN_NOTREADY)
162 return;
163
164 /* If the wavein is recording, then stop recording and close it */
167
168 /* Updating status */
170
171 /* Waking up recording thread, so it can receive
172 the `MM_WIM_CLOSE' message then dies */
175
176 /* Closing wavein stream */
178 Sleep(1);
179
180 /* Release buffers memory */
182
183 /* Re-initialize variables to the initial state */
184 init_();
185}
186
187void
189{
191 HANDLE recthread_handle = 0;
192
193 /* Checkin the status of the object */
194 if (status != WAVEIN_NOTREADY)
195 {
196 /* TODO: throw error */
197 }
198
199 /* Creating the EVENT object that will be signaled
200 when the recording thread has to wake up */
202
204
206 {
208 MessageBox(0, TEXT("Thread Error."), 0, 0);
209 /* TODO: throw error */
210 }
211
212 /* Inialize buffers for recording audio data from the wavein audio line */
215
216 /* Sound format that will be captured by wavein */
223
224 /* Creating the recording thread */
225 recthread_handle = CreateThread(NULL,
226 0,
228 (PVOID)this,
229 0,
230 &recthread_id);
231 /* Checking thread handle */
232 if (!recthread_handle)
233 {
234 /* Updating status */
236 MessageBox(0, TEXT("Thread Error."), 0, 0);
237 /* TODO: throw error */
238 }
239
240 /* We don't need the thread handle anymore, so we can close it from now.
241 (We'll just need the thread ID for the `waveInOpen' API) */
242 CloseHandle(recthread_handle);
243
244 /* Opening audio line wavein */
246 0,
249 0,
251
252 if (err != MMSYSERR_NOERROR)
253 {
254 /* Updating status */
256
257 if (err == WAVERR_BADFORMAT)
258 MessageBox(0, TEXT("waveInOpen Error"), 0, 0);
259
260 /* TODO: throw error */
261 }
262
263 /* Update object status */
265
266 /* Now `audio_wavein' object is ready for audio recording! */
267}
268
269void
271{
273 BOOL ev;
274
275 if ((status != WAVEIN_READY) && (status != WAVEIN_STOP))
276 {
277 /* TODO: throw error */
278 }
279
280 /* Updating to the recording status */
282
283 /* Let's prepare header of type WAVEHDR that we will pass to the driver
284 with our audio informations, and buffer informations */
286
287 /* The waveInAddBuffer function sends an input buffer to the given waveform-audio
288 input device. When the buffer is filled, the application is notified. */
290
291 /* Signaling event for waking up the recorder thread */
293 if (!ev)
294 MessageBox(0, TEXT("Event Error."), 0, 0);
295
296 /* Start recording */
298 if (err != MMSYSERR_NOERROR)
299 {
300 /* Updating status */
302 MessageBox(0, TEXT("waveInStart Error."), 0, 0);
303 /* TODO: throw error */
304 }
305}
306
307void
309{
311
313 return;
314
316
317 /* waveInReset will make all pending buffer as done */
319 if ( err != MMSYSERR_NOERROR )
320 {
321 /* TODO: throw error */
322 MessageBox(0, TEXT("waveInReset Error."), 0, 0);
323 }
324
327
328 /* Stop recording */
330 if (err != MMSYSERR_NOERROR)
331 {
332 /* TODO: throw error */
333 MessageBox(0, TEXT("waveInStop Error."), 0, 0);
334 }
335
336 /* The waveInUnprepareHeader function cleans up the preparation performed
337 by the waveInPrepareHeader function */
339
341}
342
345{
346 MSG msg;
347 WAVEHDR *phdr;
348 audio_wavein *_this = (audio_wavein *)arg;
349
350 /* Check the arg pointer */
351 if (_this == 0)
352 return 0;
353
354 /* The thread can go to sleep for now. It will be wake up only when
355 there is audio data to be recorded */
356 if (_this->wakeup_recthread)
358
359 /* If status of the `audio_wavein' object is not ready or recording the thread can exit */
360 if ((_this->status != WAVEIN_READY) && (_this->status != WAVEIN_RECORDING))
361 return 0;
362
363 /* Entering main polling loop */
364 while (GetMessage(&msg, 0, 0, 0))
365 {
366 switch (msg.message)
367 {
368 case MM_WIM_DATA:
369 phdr = (WAVEHDR *)msg.lParam;
370
371 if ((_this->status == WAVEIN_RECORDING) ||
372 (_this->status == WAVEIN_FLUSHING))
373 {
374 if (phdr->dwFlags & WHDR_DONE)
375 {
376 /* Flushes recorded audio data to the `audio_receiver' object */
377 _this->audio_rcvd.audio_receive((unsigned char *)phdr->lpData,
378 phdr->dwBytesRecorded);
379
380 /* Updating `audio_receiver' total bytes received
381 _AFTER_ calling `audio_receive' function */
383 }
384
385 /* If status is not flushing data, then we can re-add the buffer
386 for reusing it. Otherwise, if we are flushing pending data,
387 we cannot re-add buffer because we don't need it anymore */
388 if (_this->status != WAVEIN_FLUSHING)
389 {
390 /* Let the audio driver reuse the buffer */
391 waveInAddBuffer(_this->wavein_handle, phdr, sizeof(WAVEHDR));
392 } else {
393 /* If we are flushing pending data, we have to prepare
394 to stop recording. Set WAVEHDR flag to 0, and fires
395 the event `data_flushed_event', that will wake up
396 the main thread that is sleeping into wavein_in::stop_recording()
397 member function, waiting the last `MM_WIM_DATA' message
398 that contain pending data */
399
400 phdr->dwFlags = 0;
402
403 /* The recording is going to stop, so the recording thread can go to sleep! */
405 }
406 } /* if WAVEIN_RECORDING || WAVEIN_FLUSHING */
407 break;
408
409 case MM_WIM_CLOSE:
410 /* The thread can exit now */
411 return 0;
412 break;
413 } /* end switch(msg.message) */
414 } /* end while(GetMessage(...)) */
415
416 return 0;
417}
418
#define _AUDIO_DEFAULT_WAVEINBUFSECS
Definition: audio_def.hpp:16
#define _AUDIO_NAMESPACE_START_
Definition: audio_def.hpp:24
#define _AUDIO_NAMESPACE_END_
Definition: audio_def.hpp:25
@ WAVEIN_NOTREADY
@ WAVEIN_STOP
@ WAVEIN_RECORDING
@ WAVEIN_READY
@ WAVEIN_FLUSHING
@ WAVEIN_ERR
#define msg(x)
Definition: auth_time.c:54
#define WAVE_FORMAT_PCM
Definition: constants.h:425
unsigned short int bits(void) const
unsigned int byte_rate(void) const
unsigned int sample_rate(void) const
unsigned short int channels(void) const
unsigned int block_align(void) const
virtual void audio_receive(unsigned char *, unsigned int)=0
unsigned int bytes_received
HANDLE data_flushed_event
BYTE * main_buffer
void open(void)
void start_recording(void)
WAVEFORMATEX wave_format
void init_(void)
void prep_headers_(void)
audio_wavein_status status
DWORD recthread_id
void stop_recording(void)
void init_headers_(void)
void unprep_headers_(void)
HANDLE wakeup_recthread
void add_buffers_to_driver_(void)
void alloc_buffers_mem_(unsigned int, float)
audio_format aud_info
WAVEHDR * wave_headers
HWAVEIN wavein_handle
audio_receiver & audio_rcvd
void free_buffers_mem_(void)
unsigned int buffers
unsigned int mb_size
static DWORD WINAPI recording_procedure(LPVOID)
void close(void)
#define NULL
Definition: types.h:112
#define FALSE
Definition: types.h:117
#define CloseHandle
Definition: compat.h:739
HANDLE WINAPI DECLSPEC_HOTPATCH CreateThread(IN LPSECURITY_ATTRIBUTES lpThreadAttributes, IN DWORD dwStackSize, IN LPTHREAD_START_ROUTINE lpStartAddress, IN LPVOID lpParameter, IN DWORD dwCreationFlags, OUT LPDWORD lpThreadId)
Definition: thread.c:137
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:31
#define INFINITE
Definition: serial.h:102
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
const GLuint * buffers
Definition: glext.h:5916
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define TEXT(s)
Definition: k32.h:26
if(dx< 0)
Definition: linetemp.h:194
#define error(str)
Definition: mkdosfs.c:1605
UINT MMRESULT
Definition: mmsystem.h:962
#define MM_WIM_DATA
Definition: mmsystem.h:61
#define CALLBACK_THREAD
Definition: mmsystem.h:151
#define MM_WIM_CLOSE
Definition: mmsystem.h:60
#define MMSYSERR_NOERROR
Definition: mmsystem.h:96
#define WAVERR_BADFORMAT
Definition: mmsystem.h:176
#define WHDR_DONE
Definition: mmsystem.h:193
#define err(...)
DWORD nAvgBytesPerSec
Definition: audioclient.idl:43
WORD wBitsPerSample
Definition: audioclient.idl:45
DWORD nSamplesPerSec
Definition: audioclient.idl:42
Definition: ps.c:97
DWORD dwBufferLength
Definition: mmsystem.h:1015
DWORD dwFlags
Definition: mmsystem.h:1018
DWORD dwBytesRecorded
Definition: mmsystem.h:1016
LPSTR lpData
Definition: mmsystem.h:1014
DWORD WINAPI WaitForSingleObject(IN HANDLE hHandle, IN DWORD dwMilliseconds)
Definition: synch.c:82
VOID WINAPI DECLSPEC_HOTPATCH Sleep(IN DWORD dwMilliseconds)
Definition: synch.c:790
BOOL WINAPI DECLSPEC_HOTPATCH SetEvent(IN HANDLE hEvent)
Definition: synch.c:733
TW_UINT32 TW_UINT16 TW_UINT16 MSG
Definition: twain.h:1829
#define ZeroMemory
Definition: winbase.h:1712
#define CreateEvent
Definition: winbase.h:3748
#define WINAPI
Definition: msvc.h:6
UINT WINAPI waveInAddBuffer(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2717
UINT WINAPI waveInPrepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2653
UINT WINAPI waveInStop(HWAVEIN hWaveIn)
Definition: winmm.c:2764
UINT WINAPI waveInUnprepareHeader(HWAVEIN hWaveIn, WAVEHDR *lpWaveInHdr, UINT uSize)
Definition: winmm.c:2684
UINT WINAPI waveInReset(HWAVEIN hWaveIn)
Definition: winmm.c:2734
MMRESULT WINAPI waveInOpen(HWAVEIN *lphWaveIn, UINT uDeviceID, LPCWAVEFORMATEX lpFormat, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD dwFlags)
Definition: winmm.c:2623
UINT WINAPI waveInClose(HWAVEIN hWaveIn)
Definition: winmm.c:2634
UINT WINAPI waveInStart(HWAVEIN hWaveIn)
Definition: winmm.c:2749
#define GetMessage
Definition: winuser.h:5790
#define MessageBox
Definition: winuser.h:5822
char * LPSTR
Definition: xmlstorage.h:182
unsigned char BYTE
Definition: xxhash.c:193