[SNDREC32]
[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 {
130 delete[] acm_header.pbSrc;
131 acm_header.pbSrc = 0;
132 }
133
134 if (acm_header.pbDst != 0)
135 {
136 delete[] acm_header.pbDst;
137 acm_header.pbDst = 0;
138 }
139
140 /* Re-init structures */
141 init_();
142 /* Updating status */
143 stream_opened = false;
144 /* TODO: throw error */
145 MessageBox(0, _T("acmStreamUnPrepareHeader error"), _T("ERROR"), MB_ICONERROR);
146 }
147 }
148
149 err = acmStreamClose(acm_stream, 0);
150 acm_stream = 0;
151
152 if (err != MMSYSERR_NOERROR)
153 {
154 /* Free buffer memory */
155 if (acm_header.pbSrc != 0)
156 {
157 delete[] acm_header.pbSrc;
158 acm_header.pbSrc = 0;
159 }
160
161 if (acm_header.pbDst != 0)
162 {
163 delete[] acm_header.pbDst;
164 acm_header.pbDst = 0;
165 }
166
167 /* Re-init structures */
168 init_();
169 /* Updating status */
170 stream_opened = false;
171 /* TODO: throw error! */
172 MessageBox(0, _T("acmStreamClose error"), _T("ERROR"), MB_ICONERROR);
173 }
174
175 } /* if acm_stream != 0 */
176
177 /* Free buffer memory */
178 if (acm_header.pbSrc != 0)
179 delete[] acm_header.pbSrc;
180
181 if (acm_header.pbDst != 0)
182 delete[] acm_header.pbDst;
183
184 /* Re-init structures */
185 init_();
186 /* Updating status */
187 stream_opened = false;
188
189 /* ACM sream successfully closed */
190 }
191
192 void
193 audio_resampler_acm::audio_receive(unsigned char *data, unsigned int size)
194 {
195 MMRESULT err;
196
197 /* Checking for acm stream opened */
198 if (stream_opened)
199 {
200 /* Copy audio data from extern to internal source buffer */
201 memcpy(acm_header.pbSrc, data, size);
202
203 acm_header.cbSrcLength = size;
204 acm_header.cbDstLengthUsed = 0;
205
206 err = acmStreamConvert(acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN);
207
208 if (err != MMSYSERR_NOERROR)
209 {
210 /* TODO: throw error */
211 MessageBox(0, _T("acmStreamConvert error"), _T("ERROR"), MB_ICONERROR);
212 }
213
214 /* Wait for sound conversion */
215 while ((ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus) == 0);
216
217 /* Copy resampled audio, to destination buffer */
218 //memcpy(pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed);
219 }
220 }
221
222 _AUDIO_NAMESPACE_END_