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_ 223