reactos/base/applications/sndrec32/audio_resampler_acm.cpp

408 lines
6.8 KiB
C++
Raw Normal View History

/* PROJECT: ReactOS sndrec32
* LICENSE: GPL - See COPYING in the top level directory
* FILE: base/applications/sndrec32/audio_resampler_acm.cpp
* PURPOSE: Sound recording
* PROGRAMMERS: Marco Pagliaricci (irc: rendar)
*/
#include "stdafx.h"
#include "audio_resampler_acm.hpp"
Merge from amd64 branch: [SPIDER] 44002 Fix 64 bit build. (Samuel Serapión) [PAINT] 43858 Fix 64 bit warnings. (Samuel Serapión) [RAPPS] 43906 Fix 64 bit build. (Samuel Serapión) [SNDREC32] 44389 Fix 64 bit build. (Samuel Serapión) [TFTP] 41097 Fix pointer to DWORD cast. (Timo Kreuzer) [COMCTL32] 36172 Build as unicode. (Samuel Serapión) [USERMGR] 41098 Fix 2 POINTER<->DWORD casts. (Timo Kreuzer) [d3d9] 38149 Fix pointer<->ULONG cast. (Timo Kreuzer) 43839 Fix 64 bit Build. (Samuel Serapión) [DSOUND] 40753 Make DSDRIVERDESC.dnDevNode a DWORD_PTR and DSPROPERTY.InstanceId a ULONG_PTR. (Timo Kreuzer) [LSASRV] 44037 Fix 64 bit Build. (Samuel Serapión) [MMDRV] 40125 Fix 64bit build. (Samuel Serapión) [MSGINA] 40993 fix 64bit build (Timo Kreuzer) [NETSHELL] 41001 Don't cast the 1st parameter of InterlockedExchange to volatile void **, but to void ** (Timo Kreuzer) [OPENGL32] 36502 No need to assert an offset thats only used in i386 specific code. (Samuel Serapión) [POWRPROF] 41044 Don't cast NULL to DWORD. (Timo Kreuzer) 43860 Don't cast NULL to an integer type. (Samuel Serapión) [PSAPI] 38150 Fix a cast (Timo Kreuzer) [SHELL32] 38355 Use Get/SetWindowLongPtr (Samuel Serapión) 41047 Get rid of deprecated LargeInteger functions and use native int64 math instead. (Timo Kreuzer) 41048 DialogProc returns INT_PTR and not BOOL. Don't cast a pointer to LONG. Use INT_PTR instead of int for pointer math. (Timo Kreuzer) 41049 Change return type of OpenMRUListW and CreateMRUListW to HANDLE, add a comment that CREATEMRULISTW is already defined differently in explorer_new/undoc.h (Timo Kreuzer) 44601 Fix a prototype. Convert RtlLargeInteger to native int64. Fixes 64bit built. (Timo Kreuzer) [WDMAUD.DRV] 41101 Don't cast DWORD to PVOID, use UlongToPtr instead. (Timo Kreuzer) [WS2_32] 35777 fix ws2_32 spec file (Timo kreuzer) 44044 Fix ws2_32 64bit build (1 of 2) (Samuel Serapión) 44045 Fix ws2_32 64bit build (2 of 2) (Samuel Serapión) [WS2_32_NEW] 44389 Fix 64 bit built. (Samuel Serapión) svn path=/trunk/; revision=44602
2009-12-15 15:16:01 +00:00
#include <stdio.h>
_AUDIO_NAMESPACE_START_
/////////////////////////////////////////
/////// Private Functions ////////
/////////////////////////////////////////
void
audio_resampler_acm::init_( void )
{
//
// Zeroing structures
//
ZeroMemory( &acm_header, sizeof( ACMSTREAMHEADER ));
ZeroMemory( &wformat_src, sizeof( WAVEFORMATEX ));
ZeroMemory( &wformat_dst, sizeof( WAVEFORMATEX ));
//
// Setting structures sizes
//
acm_header.cbStruct = sizeof( ACMSTREAMHEADER );
wformat_src.cbSize = sizeof( WAVEFORMATEX );
wformat_dst.cbSize = sizeof( WAVEFORMATEX );
//
// Setting WAVEFORMATEX structure parameters
// according to `audio_format' in/out classes
//
wformat_src.wFormatTag = WAVE_FORMAT_PCM;
wformat_src.nSamplesPerSec = audfmt_in.sample_rate();
wformat_src.nChannels = audfmt_in.channels();
wformat_src.wBitsPerSample = audfmt_in.bits();
wformat_src.nAvgBytesPerSec = audfmt_in.byte_rate();
wformat_src.nBlockAlign = audfmt_in.block_align();
wformat_dst.wFormatTag = WAVE_FORMAT_PCM;
wformat_dst.nSamplesPerSec = audfmt_out.sample_rate();
wformat_dst.nChannels = audfmt_out.channels();
wformat_dst.wBitsPerSample = audfmt_out.bits();
wformat_dst.nAvgBytesPerSec = audfmt_out.byte_rate();
wformat_dst.nBlockAlign = audfmt_out.block_align();
//
// Init acm structures completed successfull
//
}
/////////////////////////////////////////
/////// Public Functions ////////
/////////////////////////////////////////
void
audio_resampler_acm::open( void )
{
MMRESULT err;
//
// Opens ACM stream
//
err = acmStreamOpen( &acm_stream, 0, &wformat_src, &wformat_dst,
0, 0, 0, ACM_STREAMOPENF_NONREALTIME );
if ( err != MMSYSERR_NOERROR )
{
//TODO: throw error
MessageBox( 0, _T("acmOpen error: %i"), _T("ERROR"), MB_ICONERROR );
}
//
// Calcs source buffer lenght
//
src_buflen = ( unsigned int )
(( float )audfmt_in.byte_rate() * ( float )buf_secs );
//
// Calcs destination source buffer lenght
// with help of ACM apis
//
err = acmStreamSize( acm_stream,
src_buflen, &dst_buflen, ACM_STREAMSIZEF_SOURCE );
if ( err != MMSYSERR_NOERROR )
{
//TODO: throw error
MessageBox( 0, _T("acmStreamSize error"), _T("ERROR"), MB_ICONERROR );
}
//
// Initialize ACMSTREAMHEADER structure,
// and alloc memory for source and destination
// buffers.
//
acm_header.fdwStatus = 0;
acm_header.dwUser = 0;
acm_header.pbSrc = ( LPBYTE ) new BYTE [ src_buflen ];
acm_header.cbSrcLength = src_buflen;
acm_header.cbSrcLengthUsed = 0;
acm_header.dwSrcUser = src_buflen;
acm_header.pbDst = ( LPBYTE ) new BYTE [ dst_buflen ];
acm_header.cbDstLength = dst_buflen;
acm_header.cbDstLengthUsed = 0;
acm_header.dwDstUser = dst_buflen;
//
// Give ACMSTREAMHEADER initialized correctly to the
// driver.
//
err = acmStreamPrepareHeader( acm_stream, &acm_header, 0L );
if ( err != MMSYSERR_NOERROR )
{
//TODO: throw error
MessageBox( 0, _T("acmStreamPrepareHeader error"), _T("ERROR"), MB_ICONERROR );
}
//
// ACM stream successfully opened.
//
stream_opened = true;
}
void
audio_resampler_acm::close( void )
{
MMRESULT err;
if ( acm_stream )
{
if ( acm_header.fdwStatus & ACMSTREAMHEADER_STATUSF_PREPARED )
{
acm_header.cbSrcLength = src_buflen;
acm_header.cbDstLength = dst_buflen;
err = acmStreamUnprepareHeader( acm_stream, &acm_header, 0L );
if ( err != MMSYSERR_NOERROR )
{
//
// Free buffer memory
//
if ( acm_header.pbSrc != 0 )
delete[] acm_header.pbSrc;
if ( acm_header.pbDst != 0 )
delete[] acm_header.pbDst;
//
// Re-init structures
//
init_();
//
// Updating status
//
stream_opened = false;
//TODO: throw error
MessageBox( 0, _T("acmStreamUnPrepareHeader error"), _T("ERROR"), MB_ICONERROR );
}
}
err = acmStreamClose( acm_stream, 0 );
acm_stream = 0;
if ( err != MMSYSERR_NOERROR )
{
//
// Free buffer memory
//
if ( acm_header.pbSrc != 0 )
delete[] acm_header.pbSrc;
if ( acm_header.pbDst != 0 )
delete[] acm_header.pbDst;
//
// Re-init structures
//
init_();
//
// Updating status
//
stream_opened = false;
//TODO: throw error!
MessageBox( 0, _T("acmStreamClose error"), _T("ERROR"), MB_ICONERROR );
}
}//if acm_stream != 0
//
// Free buffer memory
//
if ( acm_header.pbSrc != 0 )
delete[] acm_header.pbSrc;
if ( acm_header.pbDst != 0 )
delete[] acm_header.pbDst;
//
// Re-init structures
//
init_();
//
// Updating status
//
stream_opened = false;
//
// ACM sream successfully closed.
//
}
void
audio_resampler_acm::audio_receive( unsigned char * data, unsigned int size )
{
MMRESULT err;
//
// Checking for acm stream opened
//
if ( stream_opened )
{
//
// Copy audio data from extern to
// internal source buffer
//
memcpy( acm_header.pbSrc, data, size );
acm_header.cbSrcLength = size;
acm_header.cbDstLengthUsed = 0;
err = acmStreamConvert( acm_stream, &acm_header, ACM_STREAMCONVERTF_BLOCKALIGN );
if ( err != MMSYSERR_NOERROR )
{
//TODO: throw error
MessageBox( 0, _T("acmStreamConvert error"), _T("ERROR"), MB_ICONERROR );
}
//
// Wait for sound conversion
//
while(( ACMSTREAMHEADER_STATUSF_DONE & acm_header.fdwStatus ) == 0 );
//
// Copy resampled audio, to destination buffer.
//
//memcpy( pbOutputData, acm_header.pbDst, acm_header.cbDstLengthUsed );
}
}
_AUDIO_NAMESPACE_END_