patest_dither.c (6978B)
1 /** @file patest_dither.c 2 @ingroup test_src 3 @brief Attempt to hear difference between dithered and non-dithered signal. 4 5 This only has an effect if the native format is 16 bit. 6 7 @author Phil Burk http://www.softsynth.com 8 */ 9 /* 10 * $Id$ 11 * 12 * This program uses the PortAudio Portable Audio Library. 13 * For more information see: http://www.portaudio.com 14 * Copyright (c) 1999-2000 Ross Bencina and Phil Burk 15 * 16 * Permission is hereby granted, free of charge, to any person obtaining 17 * a copy of this software and associated documentation files 18 * (the "Software"), to deal in the Software without restriction, 19 * including without limitation the rights to use, copy, modify, merge, 20 * publish, distribute, sublicense, and/or sell copies of the Software, 21 * and to permit persons to whom the Software is furnished to do so, 22 * subject to the following conditions: 23 * 24 * The above copyright notice and this permission notice shall be 25 * included in all copies or substantial portions of the Software. 26 * 27 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 28 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 29 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 30 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR 31 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 32 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 33 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 34 */ 35 36 /* 37 * The text above constitutes the entire PortAudio license; however, 38 * the PortAudio community also makes the following non-binding requests: 39 * 40 * Any person wishing to distribute modifications to the Software is 41 * requested to send the modifications to the original developer so that 42 * they can be incorporated into the canonical version. It is also 43 * requested that these non-binding requests be included along with the 44 * license above. 45 */ 46 47 #include <stdio.h> 48 #include <math.h> 49 50 #include "portaudio.h" 51 52 #define NUM_SECONDS (5) 53 #define SAMPLE_RATE (44100) 54 #ifndef M_PI 55 #define M_PI (3.14159265) 56 #endif 57 #define TABLE_SIZE (200) 58 59 typedef struct paTestData 60 { 61 float sine[TABLE_SIZE]; 62 float amplitude; 63 int left_phase; 64 int right_phase; 65 } 66 paTestData; 67 68 /* This routine will be called by the PortAudio engine when audio is needed. 69 ** It may called at interrupt level on some machines so don't do anything 70 ** that could mess up the system like calling malloc() or free(). 71 */ 72 static int sineCallback( const void *inputBuffer, void *outputBuffer, 73 unsigned long framesPerBuffer, 74 const PaStreamCallbackTimeInfo *timeInfo, 75 PaStreamCallbackFlags statusFlags, void *userData ) 76 { 77 paTestData *data = (paTestData*)userData; 78 float *out = (float*)outputBuffer; 79 float amplitude = data->amplitude; 80 unsigned int i; 81 (void) inputBuffer; 82 83 for( i=0; i<framesPerBuffer; i++ ) 84 { 85 *out++ = amplitude * data->sine[data->left_phase]; /* left */ 86 *out++ = amplitude * data->sine[data->right_phase]; /* right */ 87 data->left_phase += 1; 88 if( data->left_phase >= TABLE_SIZE ) data->left_phase -= TABLE_SIZE; 89 data->right_phase += 3; /* higher pitch so we can distinguish left and right. */ 90 if( data->right_phase >= TABLE_SIZE ) data->right_phase -= TABLE_SIZE; 91 } 92 return 0; 93 } 94 95 /*****************************************************************************/ 96 /* 97 V18 version did not call Pa_Terminate() if Pa_Initialize() failed. 98 This V19 version ALWAYS calls Pa_Terminate(). PS. 99 */ 100 PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude ); 101 PaError PlaySine( paTestData *data, PaStreamFlags flags, float amplitude ) 102 { 103 PaStream* stream; 104 PaStreamParameters outputParameters; 105 PaError err; 106 107 data->left_phase = data->right_phase = 0; 108 data->amplitude = amplitude; 109 110 err = Pa_Initialize(); 111 if (err != paNoError) 112 goto done; 113 114 outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */ 115 if (outputParameters.device == paNoDevice) { 116 fprintf(stderr,"Error: No default output device.\n"); 117 goto done; 118 } 119 outputParameters.channelCount = 2; /* stereo output */ 120 outputParameters.hostApiSpecificStreamInfo = NULL; 121 outputParameters.sampleFormat = paFloat32; /* 32 bit floating point output. */ 122 /* When you change this, also */ 123 /* adapt the callback routine! */ 124 outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device ) 125 ->defaultLowOutputLatency; /* Low latency. */ 126 err = Pa_OpenStream( &stream, 127 NULL, /* No input. */ 128 &outputParameters, 129 SAMPLE_RATE, 130 1024, /* frames per buffer */ 131 flags, 132 sineCallback, 133 (void*)data ); 134 if (err != paNoError) 135 goto done; 136 137 err = Pa_StartStream( stream ); 138 if (err != paNoError) 139 goto done; 140 141 Pa_Sleep( NUM_SECONDS * 1000 ); 142 printf("CPULoad = %8.6f\n", Pa_GetStreamCpuLoad(stream)); 143 144 err = Pa_CloseStream( stream ); 145 done: 146 Pa_Sleep( 250 ); /* Just a small silence. */ 147 Pa_Terminate(); 148 return err; 149 } 150 151 152 /*******************************************************************/ 153 int main(void); 154 int main(void) 155 { 156 PaError err; 157 paTestData DATA; 158 int i; 159 float amplitude = 4.0 / (1<<15); 160 161 printf("PortAudio Test: output EXTREMELY QUIET sine wave with and without dithering.\n"); 162 /* initialise sinusoidal wavetable */ 163 for( i=0; i<TABLE_SIZE; i++ ) 164 { 165 DATA.sine[i] = (float) sin( ((double)i/(double)TABLE_SIZE) * M_PI * 2. ); 166 } 167 printf("\nNo treatment..\n"); fflush(stdout); 168 err = PlaySine( &DATA, paClipOff | paDitherOff, amplitude ); 169 if( err < 0 ) goto done; 170 171 printf("\nClip..\n"); 172 fflush(stdout); 173 err = PlaySine( &DATA, paDitherOff, amplitude ); 174 if( err < 0 ) goto done; 175 176 printf("\nClip and Dither..\n"); 177 fflush(stdout); 178 err = PlaySine( &DATA, paNoFlag, amplitude ); 179 done: 180 if (err) 181 { 182 fprintf( stderr, "An error occured while using the portaudio stream\n" ); 183 fprintf( stderr, "Error number: %d\n", err ); 184 fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); 185 err = 1; /* Though PlaySine() already called Pa_Terminate(), */ 186 } /* we may still call Pa_GetErrorText(). */ 187 else 188 printf("\n(Don't forget to turn the VOLUME DOWN after listening so carefully.)\n"); 189 return err; /* 0 or 1. */ 190 }