/* * - load portaudio.dll * - output device n to stdout * * win: * gcc -DWIN_DLL pa-stdout.c * (cl /DWIN_DLL /DCYGWIN pa-stdout.c) * gcc -DWIN_DLL -DPA_DLL=\"PortAudio.dll\" pa-stdout.c * * linux: * gcc pa-stdout.c -lportaudio * * [select SDR Audio Output channel] * ./pa-stdout.exe --list * ./pa-stdout.exe [devNo] | ./rs41mod.exe -vx --ptu * ./pa-stdout.exe --line [lineNo] | ./rs41mod.exe -vx --ptu */ #include #include #include #ifdef WIN_DLL #include #endif #ifdef CYGWIN #include // cygwin: _setmode() #include #endif #ifndef WIN_DLL #include "portaudio.h" #else // //------------------------------------------------------------------------------------------------------ #define paNoDevice ((PaDeviceIndex)-1) #define paClipOff ((PaStreamFlags) 0x00000001) #define paFloat32 ((PaSampleFormat) 0x00000001) /**< @see PaSampleFormat */ #define paInt32 ((PaSampleFormat) 0x00000002) /**< @see PaSampleFormat */ #define paInt24 ((PaSampleFormat) 0x00000004) /**< Packed 24 bit format. @see PaSampleFormat */ #define paInt16 ((PaSampleFormat) 0x00000008) /**< @see PaSampleFormat */ #define paInt8 ((PaSampleFormat) 0x00000010) /**< @see PaSampleFormat */ #define paUInt8 ((PaSampleFormat) 0x00000020) /**< @see PaSampleFormat */ #define paCustomFormat ((PaSampleFormat) 0x00010000) /**< @see PaSampleFormat */ typedef int PaError; typedef enum PaErrorCode { paNoError = 0, paNotInitialized = -10000, paUnanticipatedHostError, paInvalidChannelCount, paInvalidSampleRate, paInvalidDevice, paInvalidFlag, paSampleFormatNotSupported, paBadIODeviceCombination, paInsufficientMemory, paBufferTooBig, paBufferTooSmall, paNullCallback, paBadStreamPtr, paTimedOut, paInternalError, paDeviceUnavailable, paIncompatibleHostApiSpecificStreamInfo, paStreamIsStopped, paStreamIsNotStopped, paInputOverflowed, paOutputUnderflowed, paHostApiNotFound, paInvalidHostApi, paCanNotReadFromACallbackStream, paCanNotWriteToACallbackStream, paCanNotReadFromAnOutputOnlyStream, paCanNotWriteToAnInputOnlyStream, paIncompatibleStreamHostApi, paBadBufferPtr } PaErrorCode; typedef int PaDeviceIndex; typedef int PaHostApiIndex; typedef double PaTime; typedef struct PaDeviceInfo { int structVersion; /* this is struct version 2 */ const char *name; PaHostApiIndex hostApi; /**< note this is a host API index, not a type id*/ int maxInputChannels; int maxOutputChannels; /** Default latency values for interactive performance. */ PaTime defaultLowInputLatency; PaTime defaultLowOutputLatency; /** Default latency values for robust non-interactive applications (eg. playing sound files). */ PaTime defaultHighInputLatency; PaTime defaultHighOutputLatency; double defaultSampleRate; } PaDeviceInfo; typedef unsigned long PaStreamFlags; typedef unsigned long PaSampleFormat; typedef struct PaStreamCallbackTimeInfo{ PaTime inputBufferAdcTime; /**< The time when the first sample of the input buffer was captured at the ADC input */ PaTime currentTime; /**< The time when the stream callback was invoked */ PaTime outputBufferDacTime; /**< The time when the first sample of the output buffer will output the DAC */ } PaStreamCallbackTimeInfo; typedef unsigned long PaStreamCallbackFlags; typedef struct PaStreamParameters { PaDeviceIndex device; int channelCount; PaSampleFormat sampleFormat; PaTime suggestedLatency; void *hostApiSpecificStreamInfo; } PaStreamParameters; typedef void PaStream; typedef int PaStreamCallback( const void *input, void *output, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void *userData ); // //------------------------------------------------------------------------------------------------------ // load WIN-DLL // prototypes ( __cdecl -> WINAPIV , __stdcall -> WINAPI ) #define CALLCONV WINAPIV // __cdecl typedef int (CALLCONV* t_Pa_Initialize)(void); typedef int (CALLCONV* t_Pa_GetDefaultInputDevice)(void); typedef int (CALLCONV* t_Pa_GetDeviceCount)(void); typedef PaDeviceInfo* (CALLCONV* t_Pa_GetDeviceInfo)(PaDeviceIndex device); t_Pa_Initialize Pa_Initialize; t_Pa_GetDefaultInputDevice Pa_GetDefaultInputDevice; t_Pa_GetDeviceCount Pa_GetDeviceCount; t_Pa_GetDeviceInfo Pa_GetDeviceInfo; typedef int (CALLCONV* t_Pa_OpenStream)(PaStream**,PaStreamParameters*,PaStreamParameters*,double, unsigned long,PaStreamFlags,PaStreamCallback*,void*); typedef int (CALLCONV* t_Pa_StartStream)(PaStream*); typedef int (CALLCONV* t_Pa_ReadStream)(PaStream*,void*,unsigned long); typedef int (CALLCONV* t_Pa_CloseStream)(PaStream*); typedef int (CALLCONV* t_Pa_Terminate)(void); typedef char* (CALLCONV* t_Pa_GetErrorText)(PaError); t_Pa_OpenStream Pa_OpenStream; t_Pa_StartStream Pa_StartStream; t_Pa_ReadStream Pa_ReadStream; t_Pa_CloseStream Pa_CloseStream; t_Pa_Terminate Pa_Terminate; t_Pa_GetErrorText Pa_GetErrorText; HINSTANCE pa_handle; int adr_functions() { int ret = 0; Pa_Initialize = (t_Pa_Initialize)GetProcAddress(pa_handle, "Pa_Initialize"); if (Pa_Initialize == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_GetDefaultInputDevice = (t_Pa_GetDefaultInputDevice)GetProcAddress(pa_handle, "Pa_GetDefaultInputDevice"); if (Pa_GetDefaultInputDevice == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_GetDeviceCount = (t_Pa_GetDeviceCount)GetProcAddress(pa_handle, "Pa_GetDeviceCount"); if (Pa_GetDeviceCount == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_GetDeviceInfo = (t_Pa_GetDeviceInfo)GetProcAddress(pa_handle, "Pa_GetDeviceInfo"); if (Pa_GetDeviceInfo == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_OpenStream = (t_Pa_OpenStream)GetProcAddress(pa_handle, "Pa_OpenStream"); if (Pa_OpenStream == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_StartStream = (t_Pa_StartStream)GetProcAddress(pa_handle, "Pa_StartStream"); if (Pa_StartStream == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_ReadStream = (t_Pa_ReadStream)GetProcAddress(pa_handle, "Pa_ReadStream"); if (Pa_ReadStream == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_CloseStream = (t_Pa_CloseStream)GetProcAddress(pa_handle, "Pa_CloseStream"); if (Pa_CloseStream == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_Terminate = (t_Pa_Terminate)GetProcAddress(pa_handle, "Pa_Terminate"); if (Pa_Terminate == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } Pa_GetErrorText = (t_Pa_GetErrorText)GetProcAddress(pa_handle, "Pa_GetErrorText"); if (Pa_GetErrorText == NULL) { fprintf(stderr, "ERROR: GetProcAddress\n"); ret = -2; } return ret; } #endif #define SAMPLE_RATE (48000) #define FRAMES_PER_BUFFER (1024) #define N_CH (0x02) // 16-bit int samples #define PA_SAMPLE_TYPE paInt16 typedef short SAMPLE; // 16-bit int get_Devices(int list) { int i; PaDeviceIndex numDevices = Pa_GetDeviceCount(); fprintf(stderr, "#devices: %d\n", numDevices); if (list) { for (i = 0; i < numDevices; i++) { const PaDeviceInfo *devInfo = Pa_GetDeviceInfo(i); fprintf(stderr, "[%2d] %s\n", i, devInfo->name); } } return numDevices; } int get_Line(int lineNo, int *devNo) { int i; const PaDeviceIndex numDevices = Pa_GetDeviceCount(); const PaDeviceInfo *devInfo = NULL; char strbuf[32]; sprintf(strbuf, "Line %d", lineNo % 100); fprintf(stderr, "#devices: %d\n", numDevices); for (i = 0; i < numDevices; i++) { devInfo = Pa_GetDeviceInfo(i); if ( strstr(devInfo->name, strbuf) ) { *devNo = i; break; } } return numDevices; } unsigned char wav_hdr[] = { // 0x80, 0xbb, 0x00, 0x00: sample_rate=48000 0x52, 0x49, 0x46, 0x46, 0x24, 0xf0, 0xff, 0x7f, 0x57, 0x41, 0x56, 0x45, 0x66, 0x6d, 0x74, 0x20, 0x10, 0x00, 0x00, 0x00, 0x01, 0x00, N_CH, 0x00, 0x80, 0xbb, 0x00, 0x00, 0x00, 0xee, 0x02, 0x00, 0x04, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0xf0, 0xff, 0x7f}; //0x10,0x00: bits/sample=16 // 0x0n, 0x00: channels=n int main(int argc, char* argv[]) { int ret = 0; int devNo = -1, numDevices = 0, list = 0, lineNo = -1; PaError err = paNoError; PaStreamParameters inputParameters; PaStream *stream; const PaDeviceInfo *devInfo = NULL; SAMPLE *dataSamples = NULL; int totalFrames; int numSamples; #ifdef CYGWIN _setmode(fileno(stdout), _O_BINARY); // _setmode(_fileno(stdout), _O_BINARY); #endif //setvbuf(stdout, NULL, _IOFBF, 128); // buffered //setvbuf(stdout, NULL, _IONBF, 0); // unbuffered setbuf(stdout, NULL); // unbuffered setbuf(stderr, NULL); #ifdef WIN_DLL { char *dll_path = "PortAudio.dll"; // x86/x64 (same as gcc/cl) // gcc -DPA_DLL=\"PortAudio_x64.dll\" ... #ifdef PA_DLL dll_path = PA_DLL; #endif pa_handle = LoadLibrary(dll_path); if (pa_handle == NULL) { fprintf(stderr, "ERROR: loadlibrary\n"); return -1; } ret = adr_functions(); if (ret != 0) goto error; } #endif err = Pa_Initialize(); if ( err != paNoError ) goto done; if (argv[1]) { devNo = -1; lineNo = -1; if (strcmp(argv[1], "--list") == 0) { list = 1; devNo = -1; } else if (strcmp(argv[1], "--line") == 0) { if (argv[2]) lineNo = atoi(argv[2]); } else { devNo = atoi(argv[1]); } if (devNo == 0 && argv[1][0] != '0') devNo = -1; } if (lineNo >= 0) numDevices = get_Line(lineNo, &devNo); else numDevices = get_Devices(list); if ( list ) goto done; if ( devNo >= numDevices ) devNo = -1; totalFrames = FRAMES_PER_BUFFER; numSamples = totalFrames * N_CH; dataSamples = (SAMPLE *) calloc( numSamples, sizeof(SAMPLE) ); if ( dataSamples == NULL ) { fprintf(stderr, "ERROR: malloc\n"); goto done; } if (devNo < 0) inputParameters.device = Pa_GetDefaultInputDevice(); else inputParameters.device = devNo; fprintf(stderr, "Input Device:\n"); devInfo = Pa_GetDeviceInfo(inputParameters.device); fprintf(stderr, "[%d] %s\n", inputParameters.device, devInfo->name); if (inputParameters.device == paNoDevice) { fprintf(stderr,"Error: No default input device.\n"); goto done; } inputParameters.channelCount = N_CH; inputParameters.sampleFormat = PA_SAMPLE_TYPE; inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency; inputParameters.hostApiSpecificStreamInfo = NULL; err = Pa_OpenStream( &stream, &inputParameters, NULL, // &outputParameters, SAMPLE_RATE, FRAMES_PER_BUFFER, paClipOff, NULL, NULL ); if ( err != paNoError ) goto done; err = Pa_StartStream( stream ); if ( err != paNoError ) goto done; fwrite( wav_hdr, 1, sizeof(wav_hdr)/*44*/, stdout ); while (1) { err = Pa_ReadStream( stream, dataSamples, totalFrames ); if ( err != paNoError ) { if ( err != paInputOverflowed) goto done; //fprintf(stderr, "Error: %d (%s)\n", err, Pa_GetErrorText( err ) ); // // dataSamples... } fwrite( dataSamples, N_CH * sizeof(SAMPLE), totalFrames, stdout ); } err = Pa_CloseStream( stream ); if ( err != paNoError ) goto done; done: Pa_Terminate(); if ( dataSamples ) free(dataSamples); if ( err != paNoError ) { fprintf( stderr, "Error number: %d\n", err ); fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) ); err = 1; /* Always return 0 or 1, but no other return codes. */ } error: #ifdef WIN_DLL FreeLibrary(pa_handle); #endif if (ret) err = ret; return err; }