443a4685618040f8f5c8254a45a63db0e51524e9
[reactos.git] / reactos / base / applications / sndrec32 / audio_resampler_acm.cpp
1 /* PROJECT: ReactOS sndrec32
2 * LICENSE: GPL - See COPYING in the top level directory
3 * FILE: base/applications/sndrec32/audio_resampler_acm.cpp
4 * PURPOSE: Sound recording
5 * PROGRAMMERS: Marco Pagliaricci (irc: rendar)
6 */
7
8 #include "stdafx.h"
9 #include "audio_resampler_acm.hpp"
10
11 _AUDIO_NAMESPACE_START_
12
13 /* Private Functions */
14
15 void
16 audio_resampler_acm::init_(void)
17 {
18 /* Zeroing structures */
19 ZeroMemory(&acm_header, sizeof(ACMSTREAMHEADER));
20 ZeroMemory(&wformat_src, sizeof(WAVEFORMATEX));
21 ZeroMemory(&wformat_dst, sizeof(WAVEFORMATEX));
22
23 /* Setting structures sizes */
24 acm_header.cbStruct = sizeof(ACMSTREAMHEADER);
25 wformat_src.cbSize = sizeof(WAVEFORMATEX);
26 wformat_dst.cbSize = sizeof(WAVEFORMATEX);
27
28 /* Setting WAVEFORMATEX structure parameters
29 according to `audio_format' in/out classes */
30
31 wformat_src.wFormatTag = WAVE_FORMAT_PCM;
32 wformat_src.nSamplesPerSec = audfmt_in.sample_rate();
33 wformat_src.nChannels = audfmt_in.channels();
34 wformat_src.wBitsPerSample = audfmt_in.bits();
35 wformat_src.nAvgBytesPerSec = audfmt_in.byte_rate();
36 wformat_src.nBlockAlign = audfmt_in.block_align();
37
38 wformat_dst.wFormatTag = WAVE_FORMAT_PCM;
39 wformat_dst.nSamplesPerSec = audfmt_out.sample_rate();
40 wformat_dst.nChannels = audfmt_out.channels();
41 wformat_dst.wBitsPerSample = audfmt_out.bits();
42 wformat_dst.nAvgBytesPerSec = audfmt_out.byte_rate();
43 wformat_dst.nBlockAlign = audfmt_out.block_align();
44
45 /* Init acm structures completed successful */
46 }
47
48 /* Public Functions */
49
50 void
51 audio_resampler_acm::open(void)
52 {
53 MMRESULT err;
54
55 /* Opens ACM stream */
56 err = acmStreamOpen(&acm_stream,
57 0,
58 &wformat_src,
59 &wformat_dst,
60 0, 0, 0,
61 ACM_STREAMOPENF_NONREALTIME);
62
63 if (err != MMSYSERR_NOERROR)
64 {
65 /* TODO: throw error */
66 MessageBox(0, _T("acmOpen error: %i"), _T("ERROR"), MB_ICONERROR);
67 }
68
69 /* Calcs source buffer length */
70 src_buflen = (unsigned int)((float)audfmt_in.byte_rate() * (float)buf_secs);
71
72 /* Calcs destination source buffer length with help of ACM apis */
73 err = acmStreamSize(acm_stream,
74 src_buflen,
75 &dst_buflen,
76 ACM_STREAMSIZEF_SOURCE);
77
78 if (err != MMSYSERR_NOERROR)
79 {
80 /* TODO: throw error */
81 MessageBox(0, _T("acmStreamSize error"), _T("ERROR"), MB_ICONERROR);
82 }
83
84 /* Initialize ACMSTREAMHEADER structure,
85 and alloc memory for source and destination buffers */
86
87 acm_header.fdwStatus = 0;
88 acm_header.dwUser = 0;
89
90 acm_header.pbSrc = (LPBYTE) new BYTE[src_buflen];
91 acm_header.cbSrcLength = src_buflen;
92 acm_header.cbSrcLengthUsed = 0;
93 acm_header.dwSrcUser = src_buflen;
94
95 acm_header.pbDst = (LPBYTE) new BYTE[dst_buflen];
96 acm_header.cbDstLength = dst_buflen;
97 acm_header.cbDstLengthUsed = 0;
98 acm_header.dwDstUser = dst_buflen;
99
100 /* Give ACMSTREAMHEADER initialized correctly to the driver */
101 err = acmStreamPrepareHeader(acm_stream, &acm_header, 0L);
102 if (err != MMSYSERR_NOERROR)
103 {
104 /* TODO: throw error */
105 MessageBox(0, _T("acmStreamPrepareHeader error"), _T("ERROR"), MB_ICONERROR);
106 }
107
108 /* ACM stream successfully opened */
109 stream_opened = true;
110 }
111
112 void
113 audio_resampler_acm::close(void)
114 {
115 MMRESULT err;
116
117 if (acm_stream)
118 {
119 if (acm_header.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED)
120 {
121 acm_header.cbSrcLength = src_buflen;
122 acm_header.cbDstLength = dst_buflen;
123
124 err = acmStreamUnprepareHeader(acm_stream, &acm_header, 0L);
125 if (err != MMSYSERR_NOERROR)
126 {
127 /* Free buffer memory */
128 if (acm_header.pbSrc != 0)
129 delete[] acm_header.pbSrc;
130
131 if (acm_header.pbDst != 0)
132 delete[] acm_header.pbDst;
133
134 /* Re-init structures */
135 init_();
136 /* Updating status */
137 stream_opened = false;
138 /* TODO: throw error */
139 MessageBox(0, _T("acmStreamUnPrepareHeader error"), _T("ERROR"), MB_ICONERROR);
140 }
141 }
142
143 err = acmStreamClose(acm_stream, 0);
144 acm_stream = 0;
145
146 if (err != MMSYSERR_NOERROR)
147 {
148 /* Free buffer memory */
149 if (acm_header.pbSrc != 0)
150 delete[] acm_header.pbSrc;
151
152 if (acm_header.pbDst != 0)
153 delete[] acm_header.pbDst;
154
155 /* Re-init structures */
156 init_();
157 /* Updating status */
158 stream_opened = false;
159 /* TODO: throw error! */
160 MessageBox(0, _T("acmStreamClose error"), _T("ERROR"), MB_ICONERROR);
161 }
162
163 } /* if acm_stream != 0 */
164
165 /* Free buffer memory */
166 if (acm_header.pbSrc != 0)
167 delete[] acm_header.pbSrc;
168
169 if (acm_header.pbDst != 0)
170 delete[] acm_header.pbDst;
171
172 /* Re-init structures */
173 init_();
174 /* Updating status */
175 stream_opened = false;
176
177 /* ACM sream successfully closed */
178 }
179
180 void
181 audio_resampler_acm::audio_receive(unsigned char *data, unsigned int size)
182 {
183 MMRESULT err;
184
185 /* Checking for acm stream opened */
186 if (stream_opened)
187 {
188 /* Copy audio data from extern to internal source buffer */
189 memcpy(acm_header.pbSrc, data, size);
190
191 acm_header.cbSrcLength = size;
192 acm_header.cbDstLengthUsed = 0;
193
194 err = acmStreamConvert(acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN);
195
196 if (err != MMSYSERR_NOERROR)
197 {
198 /* TODO: throw error */
199 MessageBox(0, _T("acmStreamConvert error"), _T("ERROR"), MB_ICONERROR);
200 }
201
202 /* Wait for sound conversion */
203 while ((ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus) == 0);
204
205 /* Copy resampled audio, to destination buffer */
206 //memcpy(pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed);
207 }
208 }
209
210 _AUDIO_NAMESPACE_END_