AudioScience HPI Version_4.24.1
|
/****************************************************************************** Test Hardware Programming Interface (HPI) using HPI functions Usage: asihpitest --help note to cleanup this file, use "astyle --style=linux -s4 asihpitest.c" Copyright (C) 1997-2017 AudioScience, Inc. All rights reserved. This software is provided 'as-is', without any express or implied warranty. In no event will AudioScience Inc. be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This copyright notice and list of conditions may not be altered or removed from any source distribution. AudioScience, Inc. <support@audioscience.com> ( This license is GPL compatible see http://www.gnu.org/licenses/license-list.html#GPLCompatibleLicenses ) ******************************************************************************/ /* Some customization defines */ // Print out the complete list of mixer controls #define DUMP_MIXER_CONTROLS 0 // Use background bus mastering if available #define USE_BBM 1 // Record instreams to files "recN.pcm" #define RECORD_TO_FILE 0 // Card polling interval in milliseconds #define POLL_INTERVAL 500 // Test runtime #define RUNTIME (15 * SECONDS) // Interval at which stream state is printed #define PRINT_INTERVAL (1 * SECONDS) //#define GET_INFO_LOOP_TEST /* End customization defines */ #define SECONDS (1000/POLL_INTERVAL) #define MINUTES (60*SECONDS) #include <stdio.h> #include <stdlib.h> #include <math.h> #include <string.h> #include <ctype.h> //#include <unistd.h> #include <getopt.h> #define HPI_BUILD_INCLUDE_INTERNAL #ifdef __APPLE__ #include <hpi/hpi.h> #include <hpi/hpidebug.h> #else #include <hpi.h> #include <hpi_version.h> #include <hpidebug.h> #endif static char *hpi_control_strings[] = HPI_CONTROL_TYPE_STRINGS; static char *hpi_src_strings[] = HPI_SOURCENODE_STRINGS; static char *hpi_dst_strings[] = HPI_DESTNODE_STRINGS; // local protos static void HandleError(hpi_err_t err); // file read/write static void THPI_WavFileOpen( short nIndex, char *pszFile ); static short THPI_WavFileRead( short nIndex, uint8_t *pbData, long lLength ); static void THPI_WavFileClose( short nIndex ); static int getch( void ); // global #define BLOCK_SIZE 32768L //30720L //6144 //12288 //16384 //19200 //9600 static uint8_t abBuffer[BLOCK_SIZE]; static short haveFiles = 0; /* Option variables */ static int instream_bbm = USE_BBM; static int outstream_bbm = USE_BBM; static unsigned int record_to_file = RECORD_TO_FILE; static unsigned int runtime = RUNTIME + 1; static unsigned int dump_mixer = 0; static int max_instreams = 999; static int max_outstreams = 999; static uint16_t wAdapterIndex = 0; static int nNumFiles = 0; static unsigned int samplerate = 48000; static unsigned int bitrate = 128000; static unsigned int channels = 2; static unsigned int format = HPI_FORMAT_PCM16_SIGNED; static unsigned int new_mode = 0; static unsigned int yes = 0; #define MAX_FILES 8 static char szFile[MAX_FILES][80] = { "", "", "", "" }; static struct option long_options[] = { {"adapter", required_argument, 0, 'a'}, {"dump-mixer", no_argument, 0, 'd'}, {"disable-bbm", no_argument, 0, 'b'}, {"yes", no_argument, 0, 'y'}, {"adapter-mode", required_argument, 0, 'm'}, {"samplerate", required_argument, 0, 's'}, {"channels", required_argument, 0, 'c'}, {"format", required_argument, 0, 'f'}, {"file-record", no_argument, 0, 'F'}, {"max-instreams", required_argument, 0, 'i'}, {"max-outstreams", required_argument, 0, 'o'}, {"runtime", required_argument, 0, 'r'}, {"version", no_argument, 0, 'V'}, {"help", no_argument, 0, 'h'}, {0, 0, 0, 0} }; static const char *short_options = "a:bc:df:Fhi:m:o:r:s:Vy?"; static const char *option_help[] = { "<adapter number> to test.", "Dump list of mixer controls.", "Disable use of background bus mastering.", "Don't prompt on error.", "Set the adapter mode. (need driver reload).", "<Hz> samplerate.", "<n> channels to play or record.", "<f> format index (see hpi.h)", "Record audio to disk files.", "<n> Max number of instreams to open.", "<n> Max number of outstreams to open.", "<runtime> in seconds.", "Show the version of this program", "Show this text." }; #ifdef _MSC_VER static void poll_delay( void ) { Sleep(POLL_INTERVAL); } #else #include <time.h> #define millisec 1000000 static struct timespec poll_interval = { 0, POLL_INTERVAL * millisec }; static void poll_delay( void ) { nanosleep(&poll_interval, 0); } #endif static void help( void ) { int i = 0; printf("\nUsage: asihpitest [options] [files to play]\n"); printf("Exercise HPI API.\n\n"); while (long_options[i].name != 0) { printf(" --%s -%c %s\n", long_options[i].name, (char)(long_options[i].val), option_help[i]); i++; } exit(0); } static void parse_options( int argc, char *argv[] ) { int c; /*********** Parse the command line options ***************/ while (1) { //int this_option_optind = optind ? optind : 1; int option_index = 0; c = getopt_long(argc, argv, short_options, long_options, &option_index); if (c == -1) break; switch (c) { case 0: printf("option %s", long_options[option_index].name); if (optarg) printf(" with arg %s", optarg); printf("\n"); break; case 'a': wAdapterIndex = atoi(optarg); break; case 'b': instream_bbm = 0; outstream_bbm = 0; break; case 'c': channels = atoi(optarg); break; case 'd': dump_mixer = 1; break; case 'y': yes = 1; break; case 'F': record_to_file = 1; break; case 'f': format = atoi(optarg); break; case 'i': max_instreams = atoi(optarg); if (max_instreams < 0) { max_instreams = -max_instreams; instream_bbm = 0; } break; case 'm': new_mode = atoi(optarg); break; case 'o': max_outstreams = atoi(optarg); if (max_outstreams < 0) { max_outstreams = -max_outstreams; outstream_bbm = 0; } break; case 'r': runtime = atoi(optarg); runtime *= SECONDS; break; case 's': samplerate = atoi(optarg); break; case 'V': printf("asihpitest version " HPI_VER_STRING "\n"); exit(0); break; case '?': case 'h': help(); break; default: printf("?? getopt returned character code 0%o ??\n", c); } } if (optind < argc) { // printf ("non-option ARGV-elements: "); nNumFiles = 0; while ((optind < argc) && (nNumFiles < MAX_FILES)) { strcpy(szFile[nNumFiles], argv[optind++]); printf("File %d is %s\n", nNumFiles, szFile[nNumFiles]); nNumFiles++; } } } static void print_universal_control_lookup_result( hpi_hsubsys_t *hSubSys, hpi_handle_t hMixer, struct hpi_control_t asihpi_control, hpi_handle_t hControl ) { static hpi_handle_t block_object; char name[256]; hpi_err_t err; size_t size; size_t items; enum e_entity_role r; hpi_handle_t found_control; size = sizeof(name); err = HPI_Object_GetInfo( hControl, entity_type_cstring, entity_role_classname, name, &size, &items); if (err) HandleError(err); err = HPI_Object_GetRole(hControl, &r); if (err) HandleError(err); if ( r == entity_role_block ) { block_object = hControl; /* test lookup block by name */ err = HPI_Object_BlockHandle(hMixer, asihpi_control.wSrcNodeType, asihpi_control.wSrcNodeIndex, asihpi_control.wDstNodeType, asihpi_control.wDstNodeIndex, name, &found_control ); } else if ( r == entity_role_parameter_port ) { /* test lookup parameter by name */ err = HPI_Object_ParameterHandle( hMixer, block_object, name, &found_control); } if (err) { HandleError(err); printf(" Block/Param lookup (FAILED) "); } } static void print_universal_control( hpi_hsubsys_t *hSubSys, hpi_handle_t hMixer, hpi_handle_t hControl ) { struct hpi_entity *info; enum e_entity_role r; hpi_err_t err; char name[256]; char units[256]; size_t size, items; int flags; err = HPI_Object_GetInfoEntity(hControl, &info); printf("%s", HPI_Entity_GetRoleName(info)); size = sizeof(name); err = HPI_Object_GetInfo( hControl, entity_type_cstring, entity_role_classname, name, &size, &items); if (err) HandleError(err); printf(" %s\n", name); err = HPI_Object_GetRole(hControl, &r); if (err) HandleError(err); if ( r == entity_role_parameter_port ) { struct hpi_entity *value; enum e_entity_type the_type; const char *type; void *v; printf("Value ("); // flags size = sizeof(flags); err = HPI_Object_GetInfo( hControl, entity_type_int, entity_role_flags, &flags, &size, &items); if (flags & entity_flag_readable) printf("R"); if (flags & entity_flag_writeable) printf("W"); if (flags & entity_flag_volatile) printf("Volatile"); printf(") "); err = HPI_Object_GetValueEntity(hControl, &value); err = HPI_Entity_Unpack(value, &the_type, &items, &r, &v); type = HPI_Entity_GetTypeName(value); if (!err) { int vi; printf("%s[%zd]=[ ", type, items); if (the_type == entity_type_mac_address) { the_type = entity_type_octet; items *= 6; } for (vi = 0; vi < items; vi++) { switch (the_type) { case entity_type_int: printf("%d ", ((int *)v)[vi]); break; case entity_type_float: printf("%f ", ((float *)v)[vi]); break; case entity_type_boolean: printf("%c ", ((char *)v)[vi]); break; case entity_type_cstring: printf("%c", ((char *)v)[vi]); break; case entity_type_ip4_address: printf("0x%08x ", ((int*)v)[vi]); break; case entity_type_octet: default: printf("%02x ", ((unsigned char *)v)[vi]); break; } } printf("] "); } HPI_Entity_Free(value); // units size = sizeof(units); err = HPI_Object_GetInfo( hControl, entity_type_cstring, entity_role_units, units, &size, &items); if (!err) printf("%s", units); } // fetch parameter handles if ( r == entity_role_block ) { hpi_handle_t params[16]; /* should really use count */ size_t i; size_t number; number = sizeof(params)/sizeof(hpi_handle_t); err = HPI_Object_BlockParameters( hMixer, hControl, params, &number); if (err) HandleError(err); printf("Parameter handles=["); for ( i=0 ; i<number ; i++ ) { if (i > 0) printf(", "); printf("%d",params[i]); } printf("]"); } } static void print_mixer_controls( hpi_hsubsys_t *hSubSys, hpi_handle_t hMixer ) { int f; hpi_handle_t hControl; hpi_err_t err; for (f = 0; f < 10000; f++) { // put SOME limit to the number struct hpi_control_t asihpi_control; err = HPI_MixerGetControlByIndex(hSubSys, hMixer, f, &asihpi_control.wSrcNodeType, &asihpi_control.wSrcNodeIndex, &asihpi_control.wDstNodeType, &asihpi_control.wDstNodeIndex, &asihpi_control.wControlType, // HPI_CONTROL_METER, _VOLUME etc &hControl); if (err == HPI_ERROR_CONTROL_DISABLED) printf("DISABLED "); else if (err) break; printf("\nHPI Control %d, %s:%s[%d]->%s[%d] : ", f, hpi_control_strings[asihpi_control.wControlType], hpi_src_strings[asihpi_control.wSrcNodeType - HPI_SOURCENODE_NONE], asihpi_control.wSrcNodeIndex, hpi_dst_strings[asihpi_control.wDstNodeType - HPI_DESTNODE_NONE], asihpi_control.wDstNodeIndex); switch (asihpi_control.wControlType) { uint16_t s; uint32_t w; short db[2]; case HPI_CONTROL_MULTIPLEXER:{ int l; uint16_t cs, ci; err = HPI_Multiplexer_GetSource(hSubSys, hControl, &cs, &ci); if (err) { HandleError(err); break; } for (l = 0; l < 256; l++) { err = HPI_Multiplexer_QuerySource (hSubSys, hControl, l, &asihpi_control.wSrcNodeType, &asihpi_control. wSrcNodeIndex); if (!err) { if ((cs == asihpi_control. wSrcNodeType) && (ci == asihpi_control. wSrcNodeIndex)) printf("\n->"); else printf("\n"); printf("\tSource %d %s[%d]", l, hpi_src_strings [asihpi_control. wSrcNodeType - HPI_SOURCENODE_NONE], asihpi_control. wSrcNodeIndex); } else break; } break; } case HPI_CONTROL_VOLUME: err = HPI_VolumeGetGain(hSubSys, hControl, db); if (err) { HandleError(err); break; } printf("%5.2fdB %5.2fdB", db[0] / 100.0, db[1] / 100.0); break; case HPI_CONTROL_LEVEL: err = HPI_LevelGetGain(hSubSys, hControl, db); if (err) { HandleError(err); break; } printf("%5.2fdB %5.2fdB", db[0] / 100.0, db[1] / 100.0); break; case HPI_CONTROL_METER: err = HPI_MeterGetPeak(hSubSys, hControl, db); if (err) { HandleError(err); break; } printf("%5.2fdB %5.2fdB", db[0] / 100.0, db[1] / 100.0); break; case HPI_CONTROL_AESEBU_RECEIVER: err = HPI_AESEBU_Receiver_GetErrorStatus(hSubSys, hControl, &s); printf("status %02x", s); err = HPI_AESEBU_Receiver_GetFormat(hSubSys, hControl, &s); printf(" format %d", s); err = HPI_AESEBU_Receiver_GetSampleRate(hSubSys, hControl, &w); if (!err) printf(" rate %d", w); break; case HPI_CONTROL_SAMPLECLOCK: err = HPI_SampleClock_GetSampleRate(hSubSys, hControl, &w); err = HPI_SampleClock_GetSource(hSubSys, hControl, &s); printf("rate %d, source %d", w, s); break; case HPI_CONTROL_UNIVERSAL: print_universal_control_lookup_result(hSubSys, hMixer, asihpi_control, hControl); print_universal_control(hSubSys, hMixer, hControl); break; } } printf("\n%d controls found\n", f); } /************************************** MAIN ***********************/ int main( int argc, char *argv[] ) { hpi_hsubsys_t *hSubSys; hpi_err_t err = 0; // HPI error uint32_t dwVersion = 0; uint32_t dwDataSizeW, dwDataSizeR = 0; struct hpi_format FormatW, FormatR; int numAdapters = 0; int adapterFound = 0; uint16_t wVersion; uint32_t dwSerialNumber; uint16_t wType; uint16_t wNumOutStreams; uint16_t wNumInStreams; uint32_t current_mode; hpi_handle_t hOutStream[16]; hpi_handle_t hInStream[16]; uint32_t dwStrBufferSize = 0; uint32_t dwIStrBufferSize = 0; hpi_handle_t hMixer = 0; hpi_handle_t hControl; hpi_handle_t hMeterControl = 0; hpi_handle_t ahGainControl[4] = { 0, 0, 0, 0 }; short f; uint32_t i = 0; short anGainLog[4][2]; long testcount = 0; // #include "msgsize.c" parse_options(argc, argv); printf("********************************************************************\n"); printf("\n** Test HPI using Functions **\n"); if (nNumFiles == 0) { haveFiles = 0; nNumFiles = 32; } else haveFiles = 1; // open subsystem and find adapters err = HPI_SubSysSetHostNetworkInterface(NULL, ""); if (err && (err != HPI_ERROR_INVALID_FUNC) ) { printf("HPI_SubSysSetHostNetworkInterface error\n"); HandleError(err); } printf("********************************************************************\n"); printf("HPI_SubSysCreate\n"); hSubSys = HPI_SubSysCreate(); if (hSubSys == NULL) { printf("hSubSys==NULL\n"); exit(1); } err = HPI_SubSysGetVersionEx(hSubSys, &dwVersion); HandleError(err); printf("HPI_SubSysGetVersionEx=%x\n", dwVersion); err = HPI_SubSysGetNumAdapters(hSubSys, &numAdapters); printf("%li HPI_SubSysFindAdapters found %d adapters\n ", testcount++, numAdapters); HandleError(err); if (numAdapters > HPI_MAX_ADAPTERS) numAdapters = HPI_MAX_ADAPTERS; for (i = 0; i < (uint32_t)numAdapters; i++) { uint32_t dwAdapterIndex; uint16_t wAdapterType; err = HPI_SubSysGetAdapter(hSubSys, i, &dwAdapterIndex, &wAdapterType ) ; printf("%d=%X\n ", dwAdapterIndex, wAdapterType); if (dwAdapterIndex == wAdapterIndex) adapterFound = 1; } if (!adapterFound) { printf("No adapter with index %d\n", wAdapterIndex); exit(1); } err = HPI_AdapterClose(hSubSys, wAdapterIndex); if ( err && (err != HPI_ERROR_OBJ_NOT_OPEN) ) HandleError(err); printf("HPI_AdapterClose \n"); // open 1st adapter err = HPI_AdapterOpen(hSubSys, wAdapterIndex); HandleError(err); printf("HPI_AdapterOpen \n"); #ifdef GET_INFO_LOOP_TEST while(1){ poll_delay(); err = HPI_AdapterGetInfo(hSubSys, wAdapterIndex, &wNumOutStreams, &wNumInStreams, &wVersion, &dwSerialNumber, &wType); HandleError(err); printf("HPI_AdapterGetInfo\n"); printf("Adapter ID=%4X Index=%d NumOutStreams=%d NumInStreams=%d S/N=%d\nHw Version %c%d DSP code version %03d\n", wType, wAdapterIndex, wNumOutStreams, wNumInStreams, dwSerialNumber, ((wVersion >> 3) & 0xf) + 'A', // Hw version major wVersion & 0x7, // Hw version minor ((wVersion >> 13) * 100) + ((wVersion >> 7) & 0x3f) // DSP code version ); } HPI_SubSysFree(hSubSys); return 0; #else err = HPI_AdapterGetInfo(hSubSys, wAdapterIndex, &wNumOutStreams, &wNumInStreams, &wVersion, &dwSerialNumber, &wType); HandleError(err); printf("HPI_AdapterGetInfo\n"); printf("Adapter ID=%4X Index=%d NumOutStreams=%d NumInStreams=%d S/N=%d\nHw Version %c%d DSP code version %03d\n", wType, wAdapterIndex, wNumOutStreams, wNumInStreams, dwSerialNumber, ((wVersion >> 3) & 0xf) + 'A', // Hw version major wVersion & 0x7, // Hw version minor ((wVersion >> 13) * 100) + ((wVersion >> 7) & 0x3f) // DSP code version ); // apply the max streams options if (wNumOutStreams > max_outstreams) wNumOutStreams = max_outstreams; if (wNumInStreams > max_instreams) wNumInStreams = max_instreams; if (nNumFiles > wNumOutStreams) { nNumFiles = wNumOutStreams; } err = HPI_AdapterGetMode(hSubSys, wAdapterIndex, ¤t_mode); printf("Adapter current mode %d\n", current_mode); if (new_mode && (new_mode != current_mode)) { err = HPI_AdapterSetMode(hSubSys, wAdapterIndex, new_mode); HandleError(err); printf("Changed adapter mode. Reload driver to activate.\n"); exit(0); } // open the mixer of this adapter err = HPI_MixerOpen(hSubSys, wAdapterIndex, &hMixer); printf("HPI_MixerOpen: handle=%08X\n", hMixer); HandleError(err); if (dump_mixer) print_mixer_controls(hSubSys, hMixer); err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_CLOCK_SOURCE, 0, 0, 0, HPI_CONTROL_SAMPLECLOCK, &hControl); if (!err) { err = HPI_SampleClock_SetLocalRate(hSubSys, hControl, samplerate); /* not all adapters support the above call ie ASI2416s */ if (err) printf("HPI_SampleClock_SetLocalRate() error %d\n",err); } #ifndef HPI_BUILD_NO_STREAMS if (wNumOutStreams) { // open the out_streams printf("HPI_OutStreamOpen\n"); for (f = 0; f < wNumOutStreams; f++) { err = HPI_OutStreamOpen(hSubSys, wAdapterIndex, f, &hOutStream[f] ); printf(" %i:%08X ", f, hOutStream[f]); HandleError(err); if (outstream_bbm) { printf("HPI_OutStreamHostBufferAllocate "); err = HPI_OutStreamHostBufferAllocate(hSubSys, hOutStream[f], BLOCK_SIZE); if (err == HPI_ERROR_INVALID_FUNC) outstream_bbm = 0; else HandleError(err); } err = HPI_OutStreamReset(hSubSys, hOutStream[f]); HandleError(err); // find out some info about the stream if (hOutStream[f]) { err = HPI_OutStreamGetInfoEx(hSubSys, hOutStream[f], NULL, // state &dwStrBufferSize, NULL, NULL, NULL); HandleError(err); printf(" HPI_OutStreamGetInfo %d: BufferSize=%d\n", f, dwStrBufferSize); } } } // setup format and size of data block // we will use to send audio data to out_stream // we would normally get the format directly from the file // or audio data err = HPI_FormatCreate( &FormatW, channels, format, samplerate, bitrate, 0 // no attributes ); HandleError(err); dwDataSizeW = BLOCK_SIZE / 2; if (wNumInStreams) { // if the adapter has instreams then open them printf("\nHPI_InStreamOpen "); for (f = 0; f < wNumInStreams; f++) { err = HPI_InStreamOpen(hSubSys, wAdapterIndex, f, &hInStream[f] ); printf(" %i:%08X ", f, hInStream[f]); HandleError(err); } if (wNumInStreams) { // find out some info about stream 0 err = HPI_InStreamGetInfoEx(hSubSys, hInStream[0], NULL, &dwIStrBufferSize, NULL, NULL, NULL); printf("\nHPI_InStreamGetInfo %i: BufferSize=%d\n", 0, dwStrBufferSize); HandleError(err); err = HPI_FormatCreate( &FormatR, channels, format, samplerate, bitrate, 0 // no attributes ); HandleError(err); err = HPI_InStreamQueryFormat(hSubSys, hInStream[0], &FormatR); HandleError(err); dwDataSizeR = BLOCK_SIZE / 2; err = HPI_MixerGetControl(hSubSys, hMixer, 0, 0, HPI_DESTNODE_ISTREAM, 0, HPI_CONTROL_METER, &hMeterControl); printf("HPI_MixerGetControl - PeakMeter: handle=%08X\n", hMeterControl); HandleError(err); } } if (wNumOutStreams) { printf("********************************************************************\n"); // open some audio files to play printf("Opening files \n"); for (f = 0; f < nNumFiles; f++) THPI_WavFileOpen(f, szFile[f]); //check first available open stream to make sure we can play this format for (f = 0; f < nNumFiles; f++) if (hOutStream[f]) { printf("HPI_OutStreamQueryFormat\n"); err = HPI_OutStreamQueryFormat(hSubSys, hOutStream[f], &FormatW); HandleError(err); break; } // get mixer meter control on out_stream0 err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_OSTREAM, 0, 0, 0, HPI_CONTROL_METER, &hMeterControl); printf("HPI_MixerGetControl - PeakMeter: handle=%08X\n", hMeterControl); HandleError(err); for (f = 1; f >= 0; f--) { // get mixer volume control on the connection // between out_stream0 and lineOut0 err = HPI_MixerGetControl(hSubSys, hMixer, HPI_SOURCENODE_OSTREAM, f, HPI_DESTNODE_LINEOUT, f, HPI_CONTROL_VOLUME, &ahGainControl[f] ); // HandleError( err ); Ignore the error, some adapters don't have this control if (err == 0) { printf("HPI_MixerGetControl - Volume: handle=%08X\n", ahGainControl[f]); // test - set gain on stream anGainLog[f][0] = 0; //-4*f; anGainLog[f][1] = 0; // -4*f-2; err = HPI_VolumeSetGain(hSubSys, ahGainControl[f], anGainLog[f] ); HandleError(err); } } } { uint16_t wState = 0; uint32_t dwDataToPlay = 0; FILE *recfile[8]; char recname[] = "rec0.pcm"; // preload buffer of stream if (wNumOutStreams) { printf("Preload\n"); for (f = 0; f < nNumFiles; f++) { if (hOutStream[f]) { for (i = 0; i < ((dwStrBufferSize - 4) / dwDataSizeW); i++) { //printf("f=%d, i=%d,bs=%d,ds=%d\n",f,i,dwStrBufferSize,DataW.dwDataSize); // out_stream #1 THPI_WavFileRead(f, abBuffer, dwDataSizeW); err = HPI_OutStreamWriteBuf (hSubSys, hOutStream[f], abBuffer, dwDataSizeW, &FormatW); HandleError(err); err = HPI_OutStreamGetInfoEx (hSubSys, hOutStream[f], &wState, NULL, &dwDataToPlay, NULL, NULL); HandleError(err); printf("[%i] D=%03d S=%d \r", f, dwDataToPlay / 1000, wState); } printf("\n"); } } // start play back printf("********************************************************************\n"); printf("HPI_OutStreamStart "); for (f = 0; f < nNumFiles; f++) { if (hOutStream[f]) { err = HPI_OutStreamStart(hSubSys, hOutStream[f] ); HandleError(err); printf("%i ", f); } } printf("\n"); } for (f = 0; f < wNumInStreams; f++) { printf("%d: ", f); if (instream_bbm) { printf("HPI_InStreamHostBufferAllocate "); err = HPI_InStreamHostBufferAllocate(hSubSys, hInStream[f], BLOCK_SIZE); if (err == HPI_ERROR_INVALID_FUNC) instream_bbm = 0; else HandleError(err); } printf("HPI_InStreamSetFormat "); err = HPI_InStreamSetFormat(hSubSys, hInStream[f], &FormatR); HandleError(err); printf("HPI_InStreamReset "); err = HPI_InStreamReset(hSubSys, hInStream[f]); HandleError(err); printf("HPI_InStreamStart \n"); err = HPI_InStreamStart(hSubSys, hInStream[f]); HandleError(err); if (record_to_file) { if (szFile[f][0]) recfile[f] = fopen(szFile[f], "w"); else { recname[3] = f + '0'; recfile[f] = fopen(recname, "w"); } } } // monitor state of streams and stop when empty // don't run anything if there are no in streams or out streams if ( wNumInStreams + wNumOutStreams == 0 ) runtime = 1; while (--runtime) { int do_print = ((runtime % PRINT_INTERVAL) == 0); poll_delay(); if (do_print && wNumInStreams) printf("IN :"); for (f = 0; f < wNumInStreams; f++) { //get state of in stream err = HPI_InStreamGetInfoEx(hSubSys, hInStream[f], &wState, NULL, &dwDataToPlay, NULL, NULL); HandleError(err); if (do_print) printf("%03d %d ", dwDataToPlay / 1000, wState); if (dwDataToPlay >= dwDataSizeR) { dwDataToPlay = dwDataSizeR; err = HPI_InStreamReadBuf(hSubSys, hInStream[f], abBuffer, dwDataToPlay); HandleError(err); if (record_to_file) fwrite(abBuffer, dwDataToPlay, 1, recfile[f]); } } if (do_print && wNumInStreams) printf("\n"); if (do_print && wNumOutStreams) printf("OUT:"); for (f = 0; f < nNumFiles; f++) { if (hOutStream[f]) { //get state of stream err = HPI_OutStreamGetInfoEx(hSubSys, hOutStream[f], &wState, NULL, &dwDataToPlay, NULL, NULL); HandleError(err); if (do_print) printf("%03d %d ", dwDataToPlay / 1000, wState); if ((dwStrBufferSize - dwDataToPlay) > dwDataSizeW) { THPI_WavFileRead(f, abBuffer, dwDataSizeW); err = HPI_OutStreamWriteBuf (hSubSys, hOutStream[f], abBuffer, dwDataSizeW, &FormatW); HandleError(err); } } } if (do_print && wNumOutStreams) printf("\n"); } if (record_to_file) for (f = 0; f < wNumInStreams; f++) fclose(recfile[f]); printf("\n"); } for (f = 0; f < nNumFiles; f++) THPI_WavFileClose(f); if (wNumOutStreams) { printf("HPI_OutStreamStop "); for (f = 0; f < nNumFiles; f++) { if (hOutStream[f]) { err = HPI_OutStreamStop(hSubSys, hOutStream[f]); printf("%i ", f); HandleError(err); } } printf("\nHPI_OutStreamClose "); for (f = 0; f < wNumOutStreams; f++) { if (hOutStream[f]) { if (outstream_bbm) err = HPI_OutStreamHostBufferFree (hSubSys, hOutStream[f]); err = HPI_OutStreamClose(hSubSys, hOutStream[f]); printf("%i ", f); HandleError(err); } } } if (wNumInStreams) { printf("\nHPI_InStreamStop \n"); err = HPI_InStreamStop(hSubSys, hInStream[0]); HandleError(err); printf("\nHPI_InStreamClose "); for (f = 0; f < wNumInStreams; f++) { if (instream_bbm) err = HPI_InStreamHostBufferFree(hSubSys, hInStream[f]); err = HPI_InStreamClose(hSubSys, hInStream[f]); printf("%i ", f); HandleError(err); } } #endif // HPI_BUILD_NO_STREAMS err = HPI_MixerClose(hSubSys, hMixer); printf("\nHPI_MixerClose\n"); HandleError(err); err = HPI_AdapterClose(hSubSys, wAdapterIndex); printf("HPI_AdapterClose\n"); HandleError(err); HPI_SubSysFree(hSubSys); return 0; #endif } /******************************THPI_WavFileOpen **********************/ FILE *gpFile[8]; static void THPI_WavFileOpen( short nIndex, char *pszFile ) { if (haveFiles) { printf("%s ", pszFile); gpFile[nIndex] = fopen(pszFile, "rb"); if (!gpFile[nIndex]) { printf("****ERROR**** - can't open file\n"); getch(); exit(0); } if (toupper(pszFile[strlen(pszFile) - 1]) == 'S') fseek(gpFile[nIndex], 512, SEEK_SET); //.DSS file else fseek(gpFile[nIndex], 0x50, SEEK_SET); //.WAV file } } /******************************THPI_WavFileRead **********************/ static short THPI_WavFileRead( short nIndex, uint8_t *pbData, long lLength ) { long lNumRead; long i = 0; uint16_t wSine; if (haveFiles) { lNumRead = fread(pbData, 1, lLength, gpFile[nIndex]); //read WAV file if (lNumRead != lLength) return (1); else return (0); } else { // setup sinewave in buffer for (i = 0; i < lLength / 4; i++) { wSine = (uint16_t)(32767 * sin(2 * 3.141592653 * i / 32)); pbData[(short)i * 4] = (uint8_t)wSine; //left LSB pbData[(short)i * 4 + 1] = (uint8_t)(wSine >> 8); //left MSB pbData[(short)i * 4 + 2] = (uint8_t)wSine; //right LSB pbData[(short)i * 4 + 3] = (uint8_t)(wSine >> 8); //right MSB } return (0); } } /******************************THPI_WavFileClose **********************/ static void THPI_WavFileClose(short nIndex) { if (haveFiles) fclose(gpFile[nIndex]); } /****************************** HandleError **********************/ static void HandleError(hpi_err_t err) { char szError[256]; char nK = 0; if (err) { HPI_GetErrorText(err, szError); printf("ERROR %d %s\n", err, szError); if (!yes) { printf("press Enter to continue, (q,Enter) to exit...\n"); nK = getch(); if (nK == 'q') exit(0); } } } static int getch( void ) { return getchar(); } /* END_OF_CODE */