--- /dev/null
+/*\r
+ * $Id: $\r
+ * Portable Audio I/O Library\r
+ * Windows MME ac3 sound output test\r
+ *\r
+ * Copyright (c) 2009 Ross Bencina\r
+ *\r
+ * Permission is hereby granted, free of charge, to any person obtaining\r
+ * a copy of this software and associated documentation files\r
+ * (the "Software"), to deal in the Software without restriction,\r
+ * including without limitation the rights to use, copy, modify, merge,\r
+ * publish, distribute, sublicense, and/or sell copies of the Software,\r
+ * and to permit persons to whom the Software is furnished to do so,\r
+ * subject to the following conditions:\r
+ *\r
+ * The above copyright notice and this permission notice shall be\r
+ * included in all copies or substantial portions of the Software.\r
+ *\r
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\r
+ * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\r
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF\r
+ * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+ */\r
+\r
+/*\r
+ * The text above constitutes the entire PortAudio license; however, \r
+ * the PortAudio community also makes the following non-binding requests:\r
+ *\r
+ * Any person wishing to distribute modifications to the Software is\r
+ * requested to send the modifications to the original developer so that\r
+ * they can be incorporated into the canonical version. It is also \r
+ * requested that these non-binding requests be included along with the \r
+ * license above.\r
+ */\r
+\r
+#include <stdio.h>\r
+#include <math.h>\r
+\r
+#include <windows.h> /* required when using pa_win_wmme.h */\r
+#include <mmsystem.h> /* required when using pa_win_wmme.h */\r
+\r
+#include "portaudio.h"\r
+#include "pa_win_wmme.h"\r
+\r
+#define NUM_SECONDS (20)\r
+#define SAMPLE_RATE (48000)\r
+#define FRAMES_PER_BUFFER (64)\r
+\r
+#ifndef M_PI\r
+#define M_PI (3.14159265)\r
+#endif\r
+\r
+#define TABLE_SIZE (100)\r
+\r
+#define CHANNEL_COUNT (2)\r
+\r
+\r
+\r
+typedef struct\r
+{\r
+ short *buffer;\r
+ int bufferSampleCount;\r
+ int playbackIndex;\r
+}\r
+paTestData;\r
+\r
+/* This routine will be called by the PortAudio engine when audio is needed.\r
+** It may called at interrupt level on some machines so don't do anything\r
+** that could mess up the system like calling malloc() or free().\r
+*/\r
+static int patestCallback( const void *inputBuffer, void *outputBuffer,\r
+ unsigned long framesPerBuffer,\r
+ const PaStreamCallbackTimeInfo* timeInfo,\r
+ PaStreamCallbackFlags statusFlags,\r
+ void *userData )\r
+{\r
+ paTestData *data = (paTestData*)userData;\r
+ short *out = (short*)outputBuffer;\r
+ unsigned long i,j;\r
+\r
+ (void) timeInfo; /* Prevent unused variable warnings. */\r
+ (void) statusFlags;\r
+ (void) inputBuffer;\r
+\r
+ /* stream out contents of data->buffer looping at end */\r
+ \r
+ for( i=0; i<framesPerBuffer; i++ )\r
+ {\r
+ for( j = 0; j < CHANNEL_COUNT; ++j ){\r
+ *out++ = data->buffer[ data->playbackIndex++ ];\r
+\r
+ if( data->playbackIndex >= data->bufferSampleCount )\r
+ data->playbackIndex = 0; /* loop at end of buffer */\r
+ }\r
+ }\r
+ \r
+ return paContinue;\r
+}\r
+\r
+/*******************************************************************/\r
+int main(int argc, char* argv[])\r
+{\r
+ PaStreamParameters outputParameters;\r
+ PaWinMmeStreamInfo wmmeStreamInfo;\r
+ PaStream *stream;\r
+ PaError err;\r
+ paTestData data;\r
+ int i;\r
+ int deviceIndex;\r
+ FILE *fp;\r
+ const char *fileName = "c:\\test_48k.ac3";\r
+ data.buffer = NULL;\r
+\r
+ printf("usage: patest_wmme_ac3 fileName [paDeviceIndex]\n");\r
+\r
+ printf("PortAudio Test: output a raw ac3 stream. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);\r
+\r
+ \r
+ if( argc >= 2 )\r
+ fileName = argv[1];\r
+\r
+ printf( "reading ac3 raw stream file %s\n", fileName );\r
+\r
+ fp = fopen( fileName, "rb" );\r
+ if( !fp ){\r
+ fprintf( stderr, "error opening ac3 file.\n" );\r
+ return -1;\r
+ }\r
+ /* get file size */\r
+ fseek( fp, 0, SEEK_END );\r
+ data.bufferSampleCount = ftell( fp ) / sizeof(short);\r
+ fseek( fp, 0, SEEK_SET );\r
+\r
+ /* allocate buffer, read the whole file into memory */\r
+ data.buffer = (short*)malloc( data.bufferSampleCount * sizeof(short) );\r
+ if( !data.buffer ){\r
+ fprintf( stderr, "error allocating buffer.\n" );\r
+ return -1;\r
+ }\r
+\r
+ fread( data.buffer, sizeof(short), data.bufferSampleCount, fp );\r
+ fclose( fp );\r
+\r
+ data.playbackIndex = 0;\r
+\r
+ err = Pa_Initialize();\r
+ if( err != paNoError ) goto error;\r
+\r
+ deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;\r
+ if( argc >= 3 ){\r
+ sscanf( argv[1], "%d", &deviceIndex );\r
+ }\r
+\r
+ printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );\r
+\r
+ \r
+ outputParameters.device = deviceIndex;\r
+ outputParameters.channelCount = CHANNEL_COUNT;\r
+ outputParameters.sampleFormat = paInt16; /* IMPORTANT must use paInt16 for WMME AC3 */\r
+ outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;\r
+ outputParameters.hostApiSpecificStreamInfo = NULL;\r
+\r
+ wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);\r
+ wmmeStreamInfo.hostApiType = paMME; \r
+ wmmeStreamInfo.version = 1;\r
+ wmmeStreamInfo.flags = paWinMmeWaveFormatDolbyAc3Spdif;\r
+ outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;\r
+\r
+\r
+ if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported ){\r
+ printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );\r
+ }else{\r
+ printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );\r
+ }\r
+\r
+ err = Pa_OpenStream(\r
+ &stream,\r
+ NULL, /* no input */\r
+ &outputParameters,\r
+ SAMPLE_RATE,\r
+ FRAMES_PER_BUFFER,\r
+ paClipOff | paDitherOff, /* IMPORTANT must disable clipping and dithering for WMME AC3 */\r
+ patestCallback,\r
+ &data );\r
+ if( err != paNoError ) goto error;\r
+\r
+ err = Pa_StartStream( stream );\r
+ if( err != paNoError ) goto error;\r
+\r
+ printf("Play for %d seconds.\n", NUM_SECONDS );\r
+ Pa_Sleep( NUM_SECONDS * 1000 );\r
+\r
+ err = Pa_StopStream( stream );\r
+ if( err != paNoError ) goto error;\r
+\r
+ err = Pa_CloseStream( stream );\r
+ if( err != paNoError ) goto error;\r
+\r
+ Pa_Terminate();\r
+ free( data.buffer );\r
+ printf("Test finished.\n");\r
+ \r
+ return err;\r
+error:\r
+ Pa_Terminate();\r
+ free( data.buffer );\r
+\r
+ fprintf( stderr, "An error occured while using the portaudio stream\n" );\r
+ fprintf( stderr, "Error number: %d\n", err );\r
+ fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );\r
+ return err;\r
+}\r
+\r