gearmulator

Emulation of classic VA synths of the late 90s/2000s that are based on Motorola 56300 family DSPs
Log | Files | Refs | Submodules | README | LICENSE

paex_wmme_surround.c (6936B)


      1 /** @file paex_wmme_surround.c
      2 	@ingroup examples_src
      3 	@brief Use WMME-specific channelMask to request 5.1 surround sound output.
      4 	@author Ross Bencina <rossb@audiomulch.com>
      5 */
      6 /*
      7  * $Id: $
      8  * Portable Audio I/O Library
      9  * Windows MME surround sound output test
     10  *
     11  * Copyright (c) 2007 Ross Bencina
     12  *
     13  * Permission is hereby granted, free of charge, to any person obtaining
     14  * a copy of this software and associated documentation files
     15  * (the "Software"), to deal in the Software without restriction,
     16  * including without limitation the rights to use, copy, modify, merge,
     17  * publish, distribute, sublicense, and/or sell copies of the Software,
     18  * and to permit persons to whom the Software is furnished to do so,
     19  * subject to the following conditions:
     20  *
     21  * The above copyright notice and this permission notice shall be
     22  * included in all copies or substantial portions of the Software.
     23  *
     24  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
     25  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
     26  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     27  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
     28  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
     29  * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
     30  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     31  */
     32 
     33 /*
     34  * The text above constitutes the entire PortAudio license; however, 
     35  * the PortAudio community also makes the following non-binding requests:
     36  *
     37  * Any person wishing to distribute modifications to the Software is
     38  * requested to send the modifications to the original developer so that
     39  * they can be incorporated into the canonical version. It is also 
     40  * requested that these non-binding requests be included along with the 
     41  * license above.
     42  */
     43 
     44 #include <stdio.h>
     45 #include <math.h>
     46 
     47 #include <windows.h>    /* required when using pa_win_wmme.h */
     48 #include <mmsystem.h>   /* required when using pa_win_wmme.h */
     49 
     50 #include "portaudio.h"
     51 #include "pa_win_wmme.h"
     52 
     53 #define NUM_SECONDS         (12)
     54 #define SAMPLE_RATE         (44100)
     55 #define FRAMES_PER_BUFFER   (64)
     56 
     57 #ifndef M_PI
     58 #define M_PI  (3.14159265)
     59 #endif
     60 
     61 #define TABLE_SIZE          (100)
     62 
     63 #define CHANNEL_COUNT       (6)
     64 
     65 
     66 
     67 typedef struct
     68 {
     69     float sine[TABLE_SIZE];
     70 	int phase;
     71 	int currentChannel;
     72 	int cycleCount;
     73 }
     74 paTestData;
     75 
     76 /* This routine will be called by the PortAudio engine when audio is needed.
     77 ** It may called at interrupt level on some machines so don't do anything
     78 ** that could mess up the system like calling malloc() or free().
     79 */
     80 static int patestCallback( const void *inputBuffer, void *outputBuffer,
     81                             unsigned long framesPerBuffer,
     82                             const PaStreamCallbackTimeInfo* timeInfo,
     83                             PaStreamCallbackFlags statusFlags,
     84                             void *userData )
     85 {
     86     paTestData *data = (paTestData*)userData;
     87     float *out = (float*)outputBuffer;
     88     unsigned long i,j;
     89 
     90     (void) timeInfo; /* Prevent unused variable warnings. */
     91     (void) statusFlags;
     92     (void) inputBuffer;
     93     
     94     for( i=0; i<framesPerBuffer; i++ )
     95     {
     96 		for( j = 0; j < CHANNEL_COUNT; ++j ){
     97 			if( j == data->currentChannel && data->cycleCount < 4410 ){
     98 				*out++ = data->sine[data->phase];
     99 				data->phase += 1 + j;	// play each channel at a different pitch so they can be distinguished
    100 				if( data->phase >= TABLE_SIZE ){
    101 					data->phase -= TABLE_SIZE;
    102 				}
    103 			}else{
    104 				*out++ = 0;
    105 			}
    106 		}
    107     
    108 		data->cycleCount++;
    109 		if( data->cycleCount > 44100 ){
    110 			data->cycleCount = 0;
    111 
    112 			++data->currentChannel;
    113 			if( data->currentChannel >= CHANNEL_COUNT )
    114 				data->currentChannel -= CHANNEL_COUNT;
    115 		}
    116 	}
    117     
    118     return paContinue;
    119 }
    120 
    121 /*******************************************************************/
    122 int main(int argc, char* argv[])
    123 {
    124     PaStreamParameters outputParameters;
    125     PaWinMmeStreamInfo wmmeStreamInfo;
    126     PaStream *stream;
    127     PaError err;
    128     paTestData data;
    129     int i;
    130     int deviceIndex;
    131 
    132     printf("PortAudio Test: output a sine blip on each channel. SR = %d, BufSize = %d, Chans = %d\n", SAMPLE_RATE, FRAMES_PER_BUFFER, CHANNEL_COUNT);
    133 
    134     err = Pa_Initialize();
    135     if( err != paNoError ) goto error;
    136 
    137 	deviceIndex = Pa_GetHostApiInfo( Pa_HostApiTypeIdToHostApiIndex( paMME ) )->defaultOutputDevice;
    138 	if( argc == 2 ){
    139 		sscanf( argv[1], "%d", &deviceIndex );
    140 	}
    141 
    142 	printf( "using device id %d (%s)\n", deviceIndex, Pa_GetDeviceInfo(deviceIndex)->name );
    143 
    144     /* initialise sinusoidal wavetable */
    145     for( i=0; i<TABLE_SIZE; i++ )
    146     {
    147         data.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. );
    148     }
    149 
    150 	data.phase = 0;
    151 	data.currentChannel = 0;
    152 	data.cycleCount = 0;
    153 
    154     outputParameters.device = deviceIndex;
    155     outputParameters.channelCount = CHANNEL_COUNT;
    156     outputParameters.sampleFormat = paFloat32; /* 32 bit floating point processing */
    157     outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
    158     outputParameters.hostApiSpecificStreamInfo = NULL;
    159 
    160     /* it's not strictly necessary to provide a channelMask for surround sound
    161        output. But if you want to be sure which channel mask PortAudio will use
    162        then you should supply one */
    163     wmmeStreamInfo.size = sizeof(PaWinMmeStreamInfo);
    164     wmmeStreamInfo.hostApiType = paMME; 
    165     wmmeStreamInfo.version = 1;
    166     wmmeStreamInfo.flags = paWinMmeUseChannelMask;
    167     wmmeStreamInfo.channelMask = PAWIN_SPEAKER_5POINT1; /* request 5.1 output format */
    168     outputParameters.hostApiSpecificStreamInfo = &wmmeStreamInfo;
    169 
    170 
    171 	if( Pa_IsFormatSupported( 0, &outputParameters, SAMPLE_RATE ) == paFormatIsSupported  ){
    172 		printf( "Pa_IsFormatSupported reports device will support %d channels.\n", CHANNEL_COUNT );
    173 	}else{
    174 		printf( "Pa_IsFormatSupported reports device will not support %d channels.\n", CHANNEL_COUNT );
    175 	}
    176 
    177     err = Pa_OpenStream(
    178               &stream,
    179               NULL, /* no input */
    180               &outputParameters,
    181               SAMPLE_RATE,
    182               FRAMES_PER_BUFFER,
    183               paClipOff,      /* we won't output out of range samples so don't bother clipping them */
    184               patestCallback,
    185               &data );
    186     if( err != paNoError ) goto error;
    187 
    188     err = Pa_StartStream( stream );
    189     if( err != paNoError ) goto error;
    190 
    191     printf("Play for %d seconds.\n", NUM_SECONDS );
    192     Pa_Sleep( NUM_SECONDS * 1000 );
    193 
    194     err = Pa_StopStream( stream );
    195     if( err != paNoError ) goto error;
    196 
    197     err = Pa_CloseStream( stream );
    198     if( err != paNoError ) goto error;
    199 
    200     Pa_Terminate();
    201     printf("Test finished.\n");
    202     
    203     return err;
    204 error:
    205     Pa_Terminate();
    206     fprintf( stderr, "An error occured while using the portaudio stream\n" );
    207     fprintf( stderr, "Error number: %d\n", err );
    208     fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
    209     return err;
    210 }
    211