AudioScience HPI  Version_4.31.1
HPI Test
Generic HPI example that includes file record and playback.

/******************************************************************************
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,
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,
name, &size, &items);
if (err)
HandleError(err);
printf(" %s\n", name);
err = HPI_Object_GetRole(hControl, &r);
if (err)
HandleError(err);
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,
&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) {
printf("%d ", ((int *)v)[vi]); break;
printf("%f ", ((float *)v)[vi]); break;
printf("%c ", ((char *)v)[vi]); break;
printf("%c", ((char *)v)[vi]); break;
printf("0x%08x ", ((int*)v)[vi]); break;
default:
printf("%02x ", ((unsigned char *)v)[vi]); break;
}
}
printf("] ");
}
// units
size = sizeof(units);
err = HPI_Object_GetInfo( hControl,
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);
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);
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 -
asihpi_control.wSrcNodeIndex,
hpi_dst_strings[asihpi_control.wDstNodeType -
asihpi_control.wDstNodeIndex);
switch (asihpi_control.wControlType) {
uint16_t s;
uint32_t w;
short db[2];
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++) {
(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 -
asihpi_control.
wSrcNodeIndex);
} else
break;
}
break;
}
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;
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;
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;
hControl, &s);
printf("status %02x", s);
err = HPI_AESEBU_Receiver_GetFormat(hSubSys, hControl,
&s);
printf(" format %d", s);
hControl, &w);
if (!err)
printf(" rate %d", w);
break;
err = HPI_SampleClock_GetSampleRate(hSubSys, hControl,
&w);
err = HPI_SampleClock_GetSource(hSubSys, hControl,
&s);
printf("rate %d, source %d", w, s);
break;
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
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, &current_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,
&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 ");
hOutStream[f], BLOCK_SIZE);
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
&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);
&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,
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,
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,
f,
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);
(hSubSys,
hOutStream[f],
abBuffer, dwDataSizeW,
&FormatW);
HandleError(err);
(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 ");
hInStream[f], BLOCK_SIZE);
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);
(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)
(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)
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 */