From 208e6fca8d4c97b0b05bb34c01f2ac6d1ecca54f Mon Sep 17 00:00:00 2001 From: Kurt Moraw Date: Sat, 7 Nov 2020 18:07:55 +0100 Subject: [PATCH] update --- WinRelease/basswasapi.dll | Bin 0 -> 14266 bytes WinRelease/hsmodem.exe | Bin 50176 -> 51200 bytes hsmodem/audio.cpp | 341 ++- hsmodem/audio_wasapi.cpp | 229 ++ hsmodem/bass.h | 2294 ++++++++--------- hsmodem/basswasapi.h | 161 ++ hsmodem/basswasapi.lib | Bin 0 -> 7164 bytes hsmodem/frame_packer.cpp | 4 +- hsmodem/hsmodem.cpp | 43 +- hsmodem/hsmodem.h | 16 +- hsmodem/hsmodem.vcxproj | 3 + hsmodem/hsmodem.vcxproj.filters | 9 + hsmodem/liquid_if.cpp | 12 +- hsmodem/speed.cpp | 63 +- hsmodem/udp.cpp | 2 + oscardata/.vs/oscardata/v16/.suo | Bin 116736 -> 116736 bytes oscardata/oscardata/ArraySend.cs | 4 +- oscardata/oscardata/Form1.Designer.cs | 394 +-- oscardata/oscardata/Form1.cs | 118 +- oscardata/oscardata/bin/Release/oscardata.exe | Bin 79872 -> 83968 bytes oscardata/oscardata/config.cs | 85 +- oscardata/oscardata/oscardata.csproj | 1 - oscardata/oscardata/udp.cs | 76 +- 23 files changed, 2389 insertions(+), 1466 deletions(-) create mode 100755 WinRelease/basswasapi.dll create mode 100755 hsmodem/audio_wasapi.cpp create mode 100755 hsmodem/basswasapi.h create mode 100644 hsmodem/basswasapi.lib diff --git a/WinRelease/basswasapi.dll b/WinRelease/basswasapi.dll new file mode 100755 index 0000000000000000000000000000000000000000..41ed83e367cb2d3269734d6a5970c7a9966fc15e GIT binary patch literal 14266 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 Bm0SP- literal 0 HcmV?d00001 diff --git a/WinRelease/hsmodem.exe b/WinRelease/hsmodem.exe index e5f27a73d767b187dd71a8837bcee02e05b81820..c7e9a8bb4bf6382372eef75176b7f10d56df76ee 100755 GIT binary patch delta 23781 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 B`Sbt) diff --git a/hsmodem/audio.cpp b/hsmodem/audio.cpp index 6638cae..34063c1 100755 --- a/hsmodem/audio.cpp +++ b/hsmodem/audio.cpp @@ -43,12 +43,13 @@ void cap_write_fifo(float sample); int pb_fifo_freespace(int nolock); void init_pipes(); -#define CHANNELS 1 // no of channels used - HRECORD rchan = 0; // recording channel BASS_INFO info; HSTREAM stream = 0; +int openpbdev = -1; +int opencapdev = -1; + /*void showDeviceInfo(BASS_DEVICEINFO info) { if (info.flags & BASS_DEVICE_ENABLED) printf("%s\n","BASS_DEVICE_ENABLED "); @@ -69,77 +70,132 @@ HSTREAM stream = 0; }*/ -#define MAXDEVSTRLEN 2000 uint8_t devstring[MAXDEVSTRLEN +100]; char PBdevs[100][256]; // stores the device names, just for diagnosis, has no real fuction char CAPdevs[100][256]; -// build string of audio devices, to be sent to application as response to Broadcast search -void enumerateAudioDevices() +// audio device description table +typedef struct { + int bassdev; // bass (basswasapi) dev no + char name[256]; // DEV name +} AUDIODEVS; + +// index is enumerated number, 0=default +AUDIODEVS audioPBdevs[100]; +AUDIODEVS audioCAPdevs[100]; +int pbanz = 0, capanz = 0; + +// populate audio device list +void readAudioDevs() { - memset(devstring, 0, sizeof(devstring)); - devstring[0] = 3; // ID for this UDP message - - // playback devices int a; - int idx = 0; + + // enter default device manually + audioPBdevs[pbanz].bassdev = -1; + strcpy(audioPBdevs[pbanz].name, "Default"); + pbanz++; + + audioCAPdevs[capanz].bassdev = -1; + strcpy(audioCAPdevs[capanz].name, "Default"); + capanz++; + +#ifdef _LINUX_ BASS_DEVICEINFO info; - - strcat((char*)(devstring + 1), "System Default"); - strcat((char*)(devstring + 1), "~"); - strcpy(PBdevs[idx++], "System Default"); - for (a = 1; BASS_GetDeviceInfo(a, &info); a++) { - printf("PB device:%d = %s\n", a, info.name); - if (strlen((char*)(devstring+1)) > MAXDEVSTRLEN) break; if (info.flags & BASS_DEVICE_ENABLED) { - strncpy(PBdevs[idx], info.name, 255); - PBdevs[idx][255] = 0; - idx++; - strcat((char*)(devstring + 1), info.name); - strcat((char*)(devstring + 1), "~"); // audio device separator + if (!strstr(info.name, "HDMI") && !strstr(info.name, "hdmi") && !strstr(info.name, "efault")) + { + audioPBdevs[pbanz].bassdev = a; + strncpy(audioPBdevs[pbanz].name, info.name, 255); + audioPBdevs[pbanz].name[255] = 0; + pbanz++; + } } } + for (a = 1; BASS_RecordGetDeviceInfo(a, &info); a++) + { + if (info.flags & BASS_DEVICE_ENABLED) + { + if (!strstr(info.name, "HDMI") && !strstr(info.name, "hdmi") && !strstr(info.name, "efault")) + { + audioCAPdevs[capanz].bassdev = a; + strncpy(audioCAPdevs[capanz].name, info.name, 255); + audioCAPdevs[capanz].name[255] = 0; + capanz++; + } + } + } +#endif + +#ifdef _WIN32_ + BASS_WASAPI_DEVICEINFO info; + for (a = 0; BASS_WASAPI_GetDeviceInfo(a, &info); a++) + { + if (!(info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED)) + { + if (!strstr(info.name, "HDMI") && !strstr(info.name, "hdmi") && !strstr(info.name, "efault")) + { + audioPBdevs[pbanz].bassdev = a; + strncpy(audioPBdevs[pbanz].name, info.name, 255); + audioPBdevs[pbanz].name[255] = 0; + pbanz++; + } + } + + if ((info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED)) + { + if (!strstr(info.name, "HDMI") && !strstr(info.name, "hdmi") && !strstr(info.name, "efault")) + { + audioCAPdevs[capanz].bassdev = a; + strncpy(audioCAPdevs[capanz].name, info.name, 255); + audioCAPdevs[capanz].name[255] = 0; + capanz++; + } + } + } +#endif +} + +void printAudioDevs() +{ + printf("PB devices:\n"); + for (int i = 0; i < pbanz; i++) + printf("idx:%d bass:%d name:%s\n", i, audioPBdevs[i].bassdev, audioPBdevs[i].name); + + printf("CAP devices:\n"); + for (int i = 0; i < capanz; i++) + printf("idx:%d bass:%d name:%s\n", i, audioCAPdevs[i].bassdev, audioCAPdevs[i].name); +} + +// build string of audio device name, to be sent to application as response to Broadcast search +// starting with PB devices, sperarator ^, capture devices +// separator between devices: ~ +void buildUdpAudioList() +{ + memset(devstring, 0, sizeof(devstring)); + devstring[0] = ' '; // placeholder for ID for this UDP message + + // playback devices + for (int i = 0; i < pbanz; i++) + { + strcat((char*)devstring, audioPBdevs[i].name); + strcat((char*)devstring, "~"); // audio device separator + } + strcat((char*)(devstring + 1), "^"); // PB, CAP separator // capture devices - BASS_DEVICEINFO recinfo; - idx = 0; - - strcat((char*)(devstring + 1), "System Default"); - strcat((char*)(devstring + 1), "~"); - strcpy(CAPdevs[idx++], "System Default"); - - for (a = 0; BASS_RecordGetDeviceInfo(a, &recinfo); a++) + for (int i = 0; i < capanz; i++) { - printf("CAP device:%d = %s\n", a, recinfo.name); - if (strlen((char*)(devstring + 1)) > MAXDEVSTRLEN) break; - if (recinfo.flags & BASS_DEVICE_ENABLED) - { - strncpy(CAPdevs[idx], recinfo.name, 255); - CAPdevs[idx][255] = 0; - idx++; - strcat((char*)(devstring + 1), recinfo.name); - strcat((char*)(devstring + 1), "~"); - } + strcat((char*)devstring, audioCAPdevs[i].name); + strcat((char*)devstring, "~"); // audio device separator } -} -/* -* Audio Device numbering: -* -* Playback: -* 0 ... no audio, we use 0 for default, which is -1 -* 1 ... audio devices -* -* Record: -* 0 ... audio devices -* we insert "Default" at position 0, and let the audio devices start with 1, so we are compatible with playback -* but in init_audio() we have to substract 1 -*/ + devstring[0] = 3; // ID for this UDP message +} uint8_t* getAudioDevicelist(int *len) { @@ -148,59 +204,89 @@ uint8_t* getAudioDevicelist(int *len) } // pbdev, capdev: -1=default device -int init_audio(int pbdev, int capdev) +int init_audio(int setpbdev, int setcapdev) { - static int f = 1; - int ocd = capdev; - - // PB devices start with 1 (0 not used, but here used for Default which is -1) - if (pbdev == 255 || pbdev == 0) pbdev = -1; - - // CAP devices start with 0, but we use 0 for Default (-1) - // so we have to substract 1 from the real devices - if (capdev == 255 || capdev == 0 || capdev == -1) capdev = -1; - else capdev--; +static int f = 1; if (f == 1) { + // do only once after program start f = 0; - enumerateAudioDevices(); + readAudioDevs(); + printAudioDevs(); + buildUdpAudioList(); init_pipes(); } - - close_audio(); + + // translate requested device numbers to bass device numbers + if (setpbdev < 0 || setpbdev >= pbanz) setpbdev = 0; + if (setcapdev < 0 || setcapdev >= capanz) setcapdev = 0; + + int pbdev = -1; + if (setpbdev >=0 && setpbdev < pbanz) pbdev = audioPBdevs[setpbdev].bassdev; + int capdev = -1; + if (setcapdev >= 0 && setcapdev < capanz) capdev = audioCAPdevs[setcapdev].bassdev; printf("init audio, caprate:%d\n",caprate); - if (pbdev != -1) - printf("playback device %d: %s\n", pbdev, PBdevs[pbdev]); - else - printf("playback device %d: %s\n", pbdev, "Default"); + printf("requested PB device: %d bassno:%d name:%s\n", setpbdev, pbdev, audioPBdevs[setpbdev].name); + printf("requested CAP device: %d bassno:%d name:%s\n", setcapdev, capdev, audioCAPdevs[setcapdev].name); - if (capdev != -1) - printf("capture device %d: %s\n", capdev, CAPdevs[ocd]); - else - printf("capture device %d: %s\n", capdev, "Default"); - // check the correct BASS was loaded - if (HIWORD(BASS_GetVersion()) != BASSVERSION) + if (HIWORD(BASS_GetVersion()) != BASSVERSION) { - printf("An incorrect version of BASS was loaded\n"); + printf("An incorrect version of BASS was loaded\n"); return -1; - } - + } + +#ifdef _WIN32_ + // use WASAPI for Windows to get exclusive access to sound card + return init_wasapi(pbdev, capdev); +#endif + +#ifdef _LINUX_ + close_audio(); + + // ===== PLAYBACK ====== + + // initialize default output device + if (!BASS_Init(pbdev, caprate, 0, NULL, NULL)) + { + printf("Can't initialize output device\n"); + return -1; + } + + // read real device number + int ret = BASS_GetDevice(); + if (ret == -1) + { + printf("BASS_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + pbdev = ret; + + // set play callback + BASS_GetInfo(&info); + stream = BASS_StreamCreate(info.freq, CHANNELS, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // sample: 32 bit float + BASS_ChannelSetAttribute(stream, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency + BASS_ChannelPlay(stream, FALSE); // start it + + // ===== CAPTURE ==== + // initalize default recording device if (!BASS_RecordInit(capdev)) { printf("Can't initialize recording device: %d\n", BASS_ErrorGetCode()); return -1; } - - // initialize default output device - if (!BASS_Init(pbdev, caprate, 0, NULL, NULL)) + + // read real device number + ret = BASS_GetDevice(); + if (ret == -1) { - printf("Can't initialize output device\n"); + printf("BASS_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode()); return -1; } + capdev = ret; // set capture callback rchan = BASS_RecordStart(caprate, CHANNELS, BASS_SAMPLE_FLOAT, RecordingCallback, 0); @@ -208,23 +294,23 @@ int init_audio(int pbdev, int capdev) printf("Can't start capturing: %d\n", BASS_ErrorGetCode()); return -1; } - - // set play callback - BASS_GetInfo(&info); - stream = BASS_StreamCreate(info.freq, CHANNELS, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream, 0); // sample: 32 bit float - BASS_ChannelSetAttribute(stream, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency - BASS_ChannelPlay(stream, FALSE); // start it printf("audio initialized\n"); + + openpbdev = pbdev; + opencapdev = capdev; return 0; +#endif } +#ifdef _LINUX_ + void close_audio() { if(stream != 0) { - printf("!close Audio Devices\n"); + printf("close Audio Devices\n"); BASS_ChannelStop(rchan); int rr = BASS_RecordFree(); if (!rr) printf("Bass_RecordFree error: %d\n", BASS_ErrorGetCode()); @@ -236,11 +322,50 @@ void close_audio() } } +void selectPBdevice() +{ + if (!BASS_SetDevice(openpbdev)) + printf("BASS_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); +} + +void selectCAPdevice() +{ + if (!BASS_SetDevice(opencapdev)) + printf("BASS_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); +} + +void setPBvolume(int v) +{ + // the volume comes in % 0..99 + // map to 0..1 + float vf = v; + vf /= 100; + + printf("set PB volume to:%d / %f [0..1]\n", v, vf ); + + selectPBdevice(); + if (!BASS_SetVolume(vf)) + printf("setPBvolume: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); +} + +void setCAPvolume(int v) +{ + // the volume comes in % 0..99 + // map to min/maxPBvol + float vf = v; + vf /= 100; + + printf("set CAP volume to:%d / %f [0..1]\n", v, vf); + + selectCAPdevice(); + if (!BASS_RecordSetInput(-1,BASS_INPUT_ON,vf)) + printf("setCAPvolume: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); +} + // capture callback -// length: bytes. short=2byte, 2channels, so it requests samples*4 BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user) { - //printf("captured %ld samples\n",length/sizeof(float)); + //printf("captured %ld samples, channels:%d\n",length/sizeof(float),CHANNELS); //measure_speed(length/sizeof(float)); float *fbuffer = (float *)buffer; @@ -269,6 +394,15 @@ DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *us return length; } +#endif // _LINUX_ + +// set volume +void setVolume(int pbcap, int v) +{ + if (pbcap == 0) setPBvolume(v); + else setCAPvolume(v); + } + // ================ thread safe fifo for audio callback routines =============== #ifdef _WIN32_ @@ -371,6 +505,26 @@ void pb_write_fifo_clear() pb_wridx = pb_rdidx = 0; } +int pb_fifo_usedBlocks() +{ +static int old_fill = 0; +int fill = 0; + + int fs = pb_fifo_freespace(0); + int used = AUDIO_PLAYBACK_BUFLEN - fs; + used /= (txinterpolfactor * UDPBLOCKLEN * 8 / bitsPerSymbol); + + if (used > 0) fill = 1; else fill = 0; + if (fill == 1 && old_fill == 0) + printf("fifo has data to send\n"); + if (fill == 0 && old_fill == 1) + printf("fifo now empty\n"); + old_fill = fill; + + //printf("free:%d used blocks:%d\n", fs, used); + return used; +} + int pb_fifo_freespace(int nolock) { int freebuf = 0; @@ -412,3 +566,4 @@ int pb_read_fifo(float *data, int elements) PB_UNLOCK(); return 1; } + diff --git a/hsmodem/audio_wasapi.cpp b/hsmodem/audio_wasapi.cpp new file mode 100755 index 0000000..395d999 --- /dev/null +++ b/hsmodem/audio_wasapi.cpp @@ -0,0 +1,229 @@ +/* +* High Speed modem to transfer data in a 2,7kHz SSB channel +* ========================================================= +* Author: DJ0ABR +* +* (c) DJ0ABR +* www.dj0abr.de +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program; if not, write to the Free Software +* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +* +* audio_wasabi.c ... functions to handle audio in/out via a soundcard uses the "BASSWASAPI" library +* wasapi is needed because we need exclusive access to the sound card which is not provided for Windows with the normal bass.lib +*/ + + +#include "hsmodem.h" + +#ifdef _WIN32_ + +#define WASAPI_CHANNELS 2 // wasapi works with 2 only + +void init_pipes(); +void cap_write_fifo(float sample); +int pb_read_fifo(float* data, int elements); +void close_wasapi(); +DWORD CALLBACK PBcallback(void* buffer, DWORD length, void* user); +DWORD CALLBACK CAPcallback(void* buffer, DWORD length, void* user); + +float minPBvol = 0; +float maxPBvol = 99; +float minCAPvol = 0; +float maxCAPvol = 99; + +extern int openpbdev; +extern int opencapdev; + +float softwareCAPvolume = 0.5; + +int init_wasapi(int pbdev, int capdev) +{ + close_wasapi(); + + // ======= init PLAYBACK device ======== + + // initialize default output device + if (!BASS_WASAPI_Init(pbdev, caprate, WASAPI_CHANNELS, BASS_WASAPI_EXCLUSIVE, 0.1f/*buffer in seconds*/, 0, PBcallback, NULL)) + { + printf("Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + + // read real device number since a -1 cannot be started + int ret = BASS_WASAPI_GetDevice(); + if (ret == -1) + { + printf("BASS_WASAPI_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + pbdev = ret; + + // read the possible volume settings + BASS_WASAPI_INFO info; + if (!BASS_WASAPI_GetInfo(&info)) + { + printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + minPBvol = info.volmin; + maxPBvol = info.volmax; + + // start playback + if (!BASS_WASAPI_Start()) + { + printf("BASS_WASAPI_Start: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + + // ======= init CAPTURE device ======== + + // initalize default recording device + if (capdev == -1) capdev = -2; // cap: -2 is the default device for input + if (!BASS_WASAPI_Init(capdev, caprate, WASAPI_CHANNELS, BASS_WASAPI_EXCLUSIVE, 0.1f/*buffer in seconds*/, 0, CAPcallback, NULL)) + { + printf("Can't initialize recording device: %d\n", BASS_ErrorGetCode()); + return -1; + } + + // read real device number since a -2 cannot be started + ret = BASS_WASAPI_GetDevice(); + if (ret == -1) + { + printf("BASS_WASAPI_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode()); + return -1; + } + capdev = ret; + + // read the possible volume settings + if (!BASS_WASAPI_GetInfo(&info)) + { + printf("BASS_WASAPI_GetInfo: %d err:%d\n", pbdev, BASS_ErrorGetCode()); + return -1; + } + minCAPvol = info.volmin; + maxCAPvol = info.volmax; + + // start recording + if (!BASS_WASAPI_Start()) + { + printf("BASS_WASAPI_Start: %d err:%d\n", capdev, BASS_ErrorGetCode()); + return -1; + } + + printf("WASAPI started successfully for PBdev:%d and CAPdev:%d\n", pbdev, capdev); + + openpbdev = pbdev; + opencapdev = capdev; + + return 0; +} + +void selectPBdevice() +{ + if (!BASS_WASAPI_SetDevice(openpbdev)) + printf("BASS_WASAPI_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); +} + +void selectCAPdevice() +{ + if (!BASS_WASAPI_SetDevice(opencapdev)) + printf("BASS_WASAPI_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode()); +} + +void setPBvolume(int v) +{ + // the volume comes in % 0..99 + // map to min/maxPBvol + float vf = v * (maxPBvol - minPBvol) / 100 + minPBvol; + + if (vf < minPBvol) vf = minPBvol; + if (vf > maxPBvol) vf = maxPBvol; + + printf("set PB volume to:%d / %f [%f..%f]\n", v, vf, minPBvol, maxPBvol); + + selectPBdevice(); + if (!BASS_WASAPI_SetVolume(BASS_WASAPI_CURVE_DB, vf)) + printf("setPBvolume: %d err:%d\n", openpbdev, BASS_ErrorGetCode()); +} + +void setCAPvolume(int v) +{ + // non of the BASS input level functions are working in WASAPI exclusive mode + // so we adjust the input level by software + softwareCAPvolume = (float)v; + softwareCAPvolume /= 50; +} + +void close_wasapi() +{ + printf("close WASAPI Audio Devices\n"); + + if (openpbdev != -1) + { + selectPBdevice(); + if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", openpbdev, BASS_ErrorGetCode()); + } + + if (opencapdev != -1) + { + selectCAPdevice(); + if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", opencapdev, BASS_ErrorGetCode()); + } +} + +DWORD CALLBACK PBcallback(void* buffer, DWORD length, void* user) +{ + float* fbuffer = (float*)buffer; + + // requested number of stereo samples: length/sizeof(float) + // requested real number of samples + int req_samples = length / sizeof(float) / WASAPI_CHANNELS; + // prepare a buffer to store the mono samples from the fifo + float* fdata = (float*)malloc(sizeof(float) * req_samples); + // read mono samples from fifo + int ret = pb_read_fifo(fdata, req_samples); + if (ret == 0) + { + // fifo empty, send 00 + memset(fdata, 0, sizeof(float) * req_samples); + } + // copy the mono samples into the stereo output buffer + int didx = 0; + for (int i = 0; i < req_samples; i++) + { + fbuffer[didx++] = fdata[i]; + fbuffer[didx++] = fdata[i]; + } + + free(fdata); + return length; +} + +DWORD CALLBACK CAPcallback(void* buffer, DWORD length, void* user) +{ + //printf("CAP callback, len:%d\n",length); + //measure_speed_bps(length/sizeof(float)/ WASAPI_CHANNELS); + + float* fbuffer = (float*)buffer; + //showbytestringf((char*)"rx: ", fbuffer, 20); + for (unsigned int i = 0; i < (length / sizeof(float)); i += WASAPI_CHANNELS) + { + cap_write_fifo(fbuffer[i]); + } + + return TRUE; // continue recording +} + +#endif // _WIN32_ diff --git a/hsmodem/bass.h b/hsmodem/bass.h index 901f9a2..e6f2416 100755 --- a/hsmodem/bass.h +++ b/hsmodem/bass.h @@ -1,1160 +1,1160 @@ -/* - BASS 2.4 C/C++ header file - Copyright (c) 1999-2019 Un4seen Developments Ltd. - - See the BASS.CHM file for more detailed documentation -*/ - -#ifndef BASS_H -#define BASS_H - -#ifdef _WIN32 -#include -typedef unsigned __int64 QWORD; -#else -#include -#define WINAPI -#define CALLBACK -typedef uint8_t BYTE; -typedef uint16_t WORD; -typedef uint32_t DWORD; -typedef uint64_t QWORD; +/* + BASS 2.4 C/C++ header file + Copyright (c) 1999-2019 Un4seen Developments Ltd. + + See the BASS.CHM file for more detailed documentation +*/ + +#ifndef BASS_H +#define BASS_H + +#ifdef _WIN32 +#include +typedef unsigned __int64 QWORD; +#else +#include +#define WINAPI +#define CALLBACK +typedef uint8_t BYTE; +typedef uint16_t WORD; +typedef uint32_t DWORD; +typedef uint64_t QWORD; #ifdef __OBJC__ #include #else -typedef int BOOL; -#endif -#ifndef TRUE -#define TRUE 1 -#define FALSE 0 -#endif -#define LOBYTE(a) (BYTE)(a) -#define HIBYTE(a) (BYTE)((a)>>8) -#define LOWORD(a) (WORD)(a) -#define HIWORD(a) (WORD)((a)>>16) -#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) -#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -#define BASSVERSION 0x204 // API version -#define BASSVERSIONTEXT "2.4" - -#ifndef BASSDEF -#define BASSDEF(f) WINAPI f -#else -#define NOBASSOVERLOADS -#endif - -typedef DWORD HMUSIC; // MOD music handle -typedef DWORD HSAMPLE; // sample handle -typedef DWORD HCHANNEL; // playing sample's channel handle -typedef DWORD HSTREAM; // sample stream handle -typedef DWORD HRECORD; // recording handle -typedef DWORD HSYNC; // synchronizer handle -typedef DWORD HDSP; // DSP handle -typedef DWORD HFX; // DX8 effect handle -typedef DWORD HPLUGIN; // Plugin handle - -// Error codes returned by BASS_ErrorGetCode -#define BASS_OK 0 // all is OK -#define BASS_ERROR_MEM 1 // memory error -#define BASS_ERROR_FILEOPEN 2 // can't open the file -#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver -#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost -#define BASS_ERROR_HANDLE 5 // invalid handle -#define BASS_ERROR_FORMAT 6 // unsupported sample format -#define BASS_ERROR_POSITION 7 // invalid position -#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called -#define BASS_ERROR_START 9 // BASS_Start has not been successfully called -#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available -#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever +typedef int BOOL; +#endif +#ifndef TRUE +#define TRUE 1 +#define FALSE 0 +#endif +#define LOBYTE(a) (BYTE)(a) +#define HIBYTE(a) (BYTE)((a)>>8) +#define LOWORD(a) (WORD)(a) +#define HIWORD(a) (WORD)((a)>>16) +#define MAKEWORD(a,b) (WORD)(((a)&0xff)|((b)<<8)) +#define MAKELONG(a,b) (DWORD)(((a)&0xffff)|((b)<<16)) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#define BASSVERSION 0x204 // API version +#define BASSVERSIONTEXT "2.4" + +#ifndef BASSDEF +#define BASSDEF(f) WINAPI f +#else +#define NOBASSOVERLOADS +#endif + +typedef DWORD HMUSIC; // MOD music handle +typedef DWORD HSAMPLE; // sample handle +typedef DWORD HCHANNEL; // playing sample's channel handle +typedef DWORD HSTREAM; // sample stream handle +typedef DWORD HRECORD; // recording handle +typedef DWORD HSYNC; // synchronizer handle +typedef DWORD HDSP; // DSP handle +typedef DWORD HFX; // DX8 effect handle +typedef DWORD HPLUGIN; // Plugin handle + +// Error codes returned by BASS_ErrorGetCode +#define BASS_OK 0 // all is OK +#define BASS_ERROR_MEM 1 // memory error +#define BASS_ERROR_FILEOPEN 2 // can't open the file +#define BASS_ERROR_DRIVER 3 // can't find a free/valid driver +#define BASS_ERROR_BUFLOST 4 // the sample buffer was lost +#define BASS_ERROR_HANDLE 5 // invalid handle +#define BASS_ERROR_FORMAT 6 // unsupported sample format +#define BASS_ERROR_POSITION 7 // invalid position +#define BASS_ERROR_INIT 8 // BASS_Init has not been successfully called +#define BASS_ERROR_START 9 // BASS_Start has not been successfully called +#define BASS_ERROR_SSL 10 // SSL/HTTPS support isn't available +#define BASS_ERROR_ALREADY 14 // already initialized/paused/whatever #define BASS_ERROR_NOTAUDIO 17 // file does not contain audio -#define BASS_ERROR_NOCHAN 18 // can't get a free channel -#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified -#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified -#define BASS_ERROR_NO3D 21 // no 3D support -#define BASS_ERROR_NOEAX 22 // no EAX support -#define BASS_ERROR_DEVICE 23 // illegal device number -#define BASS_ERROR_NOPLAY 24 // not playing -#define BASS_ERROR_FREQ 25 // illegal sample rate -#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream -#define BASS_ERROR_NOHW 29 // no hardware voices available -#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data -#define BASS_ERROR_NONET 32 // no internet connection could be opened -#define BASS_ERROR_CREATE 33 // couldn't create the file -#define BASS_ERROR_NOFX 34 // effects are not available -#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available -#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel" -#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed -#define BASS_ERROR_TIMEOUT 40 // connection timedout -#define BASS_ERROR_FILEFORM 41 // unsupported file format -#define BASS_ERROR_SPEAKER 42 // unavailable speaker -#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) -#define BASS_ERROR_CODEC 44 // codec is not available/supported -#define BASS_ERROR_ENDED 45 // the channel/file has ended -#define BASS_ERROR_BUSY 46 // the device is busy +#define BASS_ERROR_NOCHAN 18 // can't get a free channel +#define BASS_ERROR_ILLTYPE 19 // an illegal type was specified +#define BASS_ERROR_ILLPARAM 20 // an illegal parameter was specified +#define BASS_ERROR_NO3D 21 // no 3D support +#define BASS_ERROR_NOEAX 22 // no EAX support +#define BASS_ERROR_DEVICE 23 // illegal device number +#define BASS_ERROR_NOPLAY 24 // not playing +#define BASS_ERROR_FREQ 25 // illegal sample rate +#define BASS_ERROR_NOTFILE 27 // the stream is not a file stream +#define BASS_ERROR_NOHW 29 // no hardware voices available +#define BASS_ERROR_EMPTY 31 // the MOD music has no sequence data +#define BASS_ERROR_NONET 32 // no internet connection could be opened +#define BASS_ERROR_CREATE 33 // couldn't create the file +#define BASS_ERROR_NOFX 34 // effects are not available +#define BASS_ERROR_NOTAVAIL 37 // requested data/action is not available +#define BASS_ERROR_DECODE 38 // the channel is/isn't a "decoding channel" +#define BASS_ERROR_DX 39 // a sufficient DirectX version is not installed +#define BASS_ERROR_TIMEOUT 40 // connection timedout +#define BASS_ERROR_FILEFORM 41 // unsupported file format +#define BASS_ERROR_SPEAKER 42 // unavailable speaker +#define BASS_ERROR_VERSION 43 // invalid BASS version (used by add-ons) +#define BASS_ERROR_CODEC 44 // codec is not available/supported +#define BASS_ERROR_ENDED 45 // the channel/file has ended +#define BASS_ERROR_BUSY 46 // the device is busy #define BASS_ERROR_UNSTREAMABLE 47 // unstreamable file -#define BASS_ERROR_UNKNOWN -1 // some other mystery problem - -// BASS_SetConfig options -#define BASS_CONFIG_BUFFER 0 -#define BASS_CONFIG_UPDATEPERIOD 1 -#define BASS_CONFIG_GVOL_SAMPLE 4 -#define BASS_CONFIG_GVOL_STREAM 5 -#define BASS_CONFIG_GVOL_MUSIC 6 -#define BASS_CONFIG_CURVE_VOL 7 -#define BASS_CONFIG_CURVE_PAN 8 -#define BASS_CONFIG_FLOATDSP 9 -#define BASS_CONFIG_3DALGORITHM 10 -#define BASS_CONFIG_NET_TIMEOUT 11 -#define BASS_CONFIG_NET_BUFFER 12 -#define BASS_CONFIG_PAUSE_NOPLAY 13 -#define BASS_CONFIG_NET_PREBUF 15 -#define BASS_CONFIG_NET_PASSIVE 18 -#define BASS_CONFIG_REC_BUFFER 19 -#define BASS_CONFIG_NET_PLAYLIST 21 -#define BASS_CONFIG_MUSIC_VIRTUAL 22 -#define BASS_CONFIG_VERIFY 23 -#define BASS_CONFIG_UPDATETHREADS 24 -#define BASS_CONFIG_DEV_BUFFER 27 -#define BASS_CONFIG_REC_LOOPBACK 28 -#define BASS_CONFIG_VISTA_TRUEPOS 30 -#define BASS_CONFIG_IOS_SESSION 34 -#define BASS_CONFIG_IOS_MIXAUDIO 34 -#define BASS_CONFIG_DEV_DEFAULT 36 -#define BASS_CONFIG_NET_READTIMEOUT 37 -#define BASS_CONFIG_VISTA_SPEAKERS 38 -#define BASS_CONFIG_IOS_SPEAKER 39 -#define BASS_CONFIG_MF_DISABLE 40 -#define BASS_CONFIG_HANDLES 41 -#define BASS_CONFIG_UNICODE 42 -#define BASS_CONFIG_SRC 43 -#define BASS_CONFIG_SRC_SAMPLE 44 -#define BASS_CONFIG_ASYNCFILE_BUFFER 45 -#define BASS_CONFIG_OGG_PRESCAN 47 -#define BASS_CONFIG_MF_VIDEO 48 -#define BASS_CONFIG_AIRPLAY 49 -#define BASS_CONFIG_DEV_NONSTOP 50 -#define BASS_CONFIG_IOS_NOCATEGORY 51 -#define BASS_CONFIG_VERIFY_NET 52 -#define BASS_CONFIG_DEV_PERIOD 53 -#define BASS_CONFIG_FLOAT 54 -#define BASS_CONFIG_NET_SEEK 56 -#define BASS_CONFIG_AM_DISABLE 58 -#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59 -#define BASS_CONFIG_NET_PREBUF_WAIT 60 +#define BASS_ERROR_UNKNOWN -1 // some other mystery problem + +// BASS_SetConfig options +#define BASS_CONFIG_BUFFER 0 +#define BASS_CONFIG_UPDATEPERIOD 1 +#define BASS_CONFIG_GVOL_SAMPLE 4 +#define BASS_CONFIG_GVOL_STREAM 5 +#define BASS_CONFIG_GVOL_MUSIC 6 +#define BASS_CONFIG_CURVE_VOL 7 +#define BASS_CONFIG_CURVE_PAN 8 +#define BASS_CONFIG_FLOATDSP 9 +#define BASS_CONFIG_3DALGORITHM 10 +#define BASS_CONFIG_NET_TIMEOUT 11 +#define BASS_CONFIG_NET_BUFFER 12 +#define BASS_CONFIG_PAUSE_NOPLAY 13 +#define BASS_CONFIG_NET_PREBUF 15 +#define BASS_CONFIG_NET_PASSIVE 18 +#define BASS_CONFIG_REC_BUFFER 19 +#define BASS_CONFIG_NET_PLAYLIST 21 +#define BASS_CONFIG_MUSIC_VIRTUAL 22 +#define BASS_CONFIG_VERIFY 23 +#define BASS_CONFIG_UPDATETHREADS 24 +#define BASS_CONFIG_DEV_BUFFER 27 +#define BASS_CONFIG_REC_LOOPBACK 28 +#define BASS_CONFIG_VISTA_TRUEPOS 30 +#define BASS_CONFIG_IOS_SESSION 34 +#define BASS_CONFIG_IOS_MIXAUDIO 34 +#define BASS_CONFIG_DEV_DEFAULT 36 +#define BASS_CONFIG_NET_READTIMEOUT 37 +#define BASS_CONFIG_VISTA_SPEAKERS 38 +#define BASS_CONFIG_IOS_SPEAKER 39 +#define BASS_CONFIG_MF_DISABLE 40 +#define BASS_CONFIG_HANDLES 41 +#define BASS_CONFIG_UNICODE 42 +#define BASS_CONFIG_SRC 43 +#define BASS_CONFIG_SRC_SAMPLE 44 +#define BASS_CONFIG_ASYNCFILE_BUFFER 45 +#define BASS_CONFIG_OGG_PRESCAN 47 +#define BASS_CONFIG_MF_VIDEO 48 +#define BASS_CONFIG_AIRPLAY 49 +#define BASS_CONFIG_DEV_NONSTOP 50 +#define BASS_CONFIG_IOS_NOCATEGORY 51 +#define BASS_CONFIG_VERIFY_NET 52 +#define BASS_CONFIG_DEV_PERIOD 53 +#define BASS_CONFIG_FLOAT 54 +#define BASS_CONFIG_NET_SEEK 56 +#define BASS_CONFIG_AM_DISABLE 58 +#define BASS_CONFIG_NET_PLAYLIST_DEPTH 59 +#define BASS_CONFIG_NET_PREBUF_WAIT 60 #define BASS_CONFIG_ANDROID_SESSIONID 62 -#define BASS_CONFIG_WASAPI_PERSIST 65 -#define BASS_CONFIG_REC_WASAPI 66 +#define BASS_CONFIG_WASAPI_PERSIST 65 +#define BASS_CONFIG_REC_WASAPI 66 #define BASS_CONFIG_ANDROID_AAUDIO 67 - -// BASS_SetConfigPtr options -#define BASS_CONFIG_NET_AGENT 16 -#define BASS_CONFIG_NET_PROXY 17 -#define BASS_CONFIG_IOS_NOTIFY 46 -#define BASS_CONFIG_LIBSSL 64 - + +// BASS_SetConfigPtr options +#define BASS_CONFIG_NET_AGENT 16 +#define BASS_CONFIG_NET_PROXY 17 +#define BASS_CONFIG_IOS_NOTIFY 46 +#define BASS_CONFIG_LIBSSL 64 + // BASS_CONFIG_IOS_SESSION flags #define BASS_IOS_SESSION_MIX 1 #define BASS_IOS_SESSION_DUCK 2 #define BASS_IOS_SESSION_AMBIENT 4 #define BASS_IOS_SESSION_SPEAKER 8 #define BASS_IOS_SESSION_DISABLE 16 - -// BASS_Init flags -#define BASS_DEVICE_8BITS 1 // 8 bit -#define BASS_DEVICE_MONO 2 // mono -#define BASS_DEVICE_3D 4 // enable 3D functionality -#define BASS_DEVICE_16BITS 8 // limit output to 16 bit -#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct) -#define BASS_DEVICE_CPSPEAKERS 0x400 // detect speakers via Windows control panel -#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment -#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement -#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin -#define BASS_DEVICE_FREQ 0x4000 // set device sample rate -#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo -#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode -#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output -#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output - -// DirectSound interfaces (for use with BASS_GetDSoundObject) -#define BASS_OBJECT_DS 1 // IDirectSound -#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener - -// Device info structure -typedef struct { -#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) - const wchar_t *name; // description - const wchar_t *driver; // driver -#else - const char *name; // description - const char *driver; // driver -#endif - DWORD flags; -} BASS_DEVICEINFO; - -// BASS_DEVICEINFO flags -#define BASS_DEVICE_ENABLED 1 -#define BASS_DEVICE_DEFAULT 2 -#define BASS_DEVICE_INIT 4 -#define BASS_DEVICE_LOOPBACK 8 - -#define BASS_DEVICE_TYPE_MASK 0xff000000 -#define BASS_DEVICE_TYPE_NETWORK 0x01000000 -#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000 -#define BASS_DEVICE_TYPE_LINE 0x03000000 -#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000 -#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000 -#define BASS_DEVICE_TYPE_HEADSET 0x06000000 -#define BASS_DEVICE_TYPE_HANDSET 0x07000000 -#define BASS_DEVICE_TYPE_DIGITAL 0x08000000 -#define BASS_DEVICE_TYPE_SPDIF 0x09000000 -#define BASS_DEVICE_TYPE_HDMI 0x0a000000 -#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000 - -// BASS_GetDeviceInfo flags -#define BASS_DEVICES_AIRPLAY 0x1000000 - -typedef struct { - DWORD flags; // device capabilities (DSCAPS_xxx flags) - DWORD hwsize; // size of total device hardware memory - DWORD hwfree; // size of free device hardware memory - DWORD freesam; // number of free sample slots in the hardware - DWORD free3d; // number of free 3D sample slots in the hardware - DWORD minrate; // min sample rate supported by the hardware - DWORD maxrate; // max sample rate supported by the hardware - BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) - DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) - DWORD dsver; // DirectSound version - DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) - DWORD initflags; // BASS_Init "flags" parameter - DWORD speakers; // number of speakers available - DWORD freq; // current output rate -} BASS_INFO; - -// BASS_INFO flags (from DSOUND.H) -#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate -#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support -#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft -#define DSCAPS_SECONDARYMONO 0x00000100 // mono -#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo -#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit -#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit - -// Recording device info structure -typedef struct { - DWORD flags; // device capabilities (DSCCAPS_xxx flags) - DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) - DWORD inputs; // number of inputs - BOOL singlein; // TRUE = only 1 input can be set at a time - DWORD freq; // current input rate -} BASS_RECORDINFO; - -// BASS_RECORDINFO flags (from DSOUND.H) -#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support -#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft - -// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) -#ifndef WAVE_FORMAT_1M08 -#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ -#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ -#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ -#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ -#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ -#endif - -// Sample info structure -typedef struct { - DWORD freq; // default playback rate - float volume; // default volume (0-1) - float pan; // default pan (-1=left, 0=middle, 1=right) - DWORD flags; // BASS_SAMPLE_xxx flags - DWORD length; // length (in bytes) - DWORD max; // maximum simultaneous playbacks - DWORD origres; // original resolution - DWORD chans; // number of channels - DWORD mingap; // minimum gap (ms) between creating channels - DWORD mode3d; // BASS_3DMODE_xxx mode - float mindist; // minimum distance - float maxdist; // maximum distance - DWORD iangle; // angle of inside projection cone - DWORD oangle; // angle of outside projection cone - float outvol; // delta-volume outside the projection cone - DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) - DWORD priority; // priority (0=lowest, 0xffffffff=highest) -} BASS_SAMPLE; - -#define BASS_SAMPLE_8BITS 1 // 8 bit -#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point -#define BASS_SAMPLE_MONO 2 // mono -#define BASS_SAMPLE_LOOP 4 // looped -#define BASS_SAMPLE_3D 8 // 3D functionality -#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing -#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) -#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management -#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects -#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume -#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing -#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) - -#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) -#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends -#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams -#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks -#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) -#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC - -#define BASS_MP3_IGNOREDELAY 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info -#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN - -#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT -#define BASS_MUSIC_MONO BASS_SAMPLE_MONO -#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP -#define BASS_MUSIC_3D BASS_SAMPLE_3D -#define BASS_MUSIC_FX BASS_SAMPLE_FX -#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE -#define BASS_MUSIC_DECODE BASS_STREAM_DECODE -#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length -#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN -#define BASS_MUSIC_RAMP 0x200 // normal ramping -#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping -#define BASS_MUSIC_SURROUND 0x800 // surround sound -#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) -#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files -#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does -#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does -#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing -#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing -#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position -#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position -#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect -#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples - -// Speaker assignment flags -#define BASS_SPEAKER_FRONT 0x1000000 // front speakers -#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers -#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) -#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) -#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) -#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left -#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right -#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT -#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT -#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT - -#define BASS_ASYNCFILE 0x40000000 -#define BASS_UNICODE 0x80000000 - -#define BASS_RECORD_PAUSE 0x8000 // start recording paused -#define BASS_RECORD_ECHOCANCEL 0x2000 -#define BASS_RECORD_AGC 0x4000 - -// DX7 voice allocation & management flags -#define BASS_VAM_HARDWARE 1 -#define BASS_VAM_SOFTWARE 2 -#define BASS_VAM_TERM_TIME 4 -#define BASS_VAM_TERM_DIST 8 -#define BASS_VAM_TERM_PRIO 16 - -// Channel info structure -typedef struct { - DWORD freq; // default playback rate - DWORD chans; // channels - DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags - DWORD ctype; // type of channel - DWORD origres; // original resolution - HPLUGIN plugin; // plugin - HSAMPLE sample; // sample - const char *filename; // filename -} BASS_CHANNELINFO; - -#define BASS_ORIGRES_FLOAT 0x10000 - -// BASS_CHANNELINFO types -#define BASS_CTYPE_SAMPLE 1 -#define BASS_CTYPE_RECORD 2 -#define BASS_CTYPE_STREAM 0x10000 -#define BASS_CTYPE_STREAM_VORBIS 0x10002 -#define BASS_CTYPE_STREAM_OGG 0x10002 -#define BASS_CTYPE_STREAM_MP1 0x10003 -#define BASS_CTYPE_STREAM_MP2 0x10004 -#define BASS_CTYPE_STREAM_MP3 0x10005 -#define BASS_CTYPE_STREAM_AIFF 0x10006 -#define BASS_CTYPE_STREAM_CA 0x10007 -#define BASS_CTYPE_STREAM_MF 0x10008 -#define BASS_CTYPE_STREAM_AM 0x10009 -#define BASS_CTYPE_STREAM_DUMMY 0x18000 -#define BASS_CTYPE_STREAM_DEVICE 0x18001 -#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec -#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 -#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 -#define BASS_CTYPE_MUSIC_MOD 0x20000 -#define BASS_CTYPE_MUSIC_MTM 0x20001 -#define BASS_CTYPE_MUSIC_S3M 0x20002 -#define BASS_CTYPE_MUSIC_XM 0x20003 -#define BASS_CTYPE_MUSIC_IT 0x20004 -#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag - -typedef struct { - DWORD ctype; // channel type -#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) - const wchar_t *name; // format description - const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) -#else - const char *name; // format description - const char *exts; // file extension filter (*.ext1;*.ext2;etc...) -#endif -} BASS_PLUGINFORM; - -typedef struct { - DWORD version; // version (same form as BASS_GetVersion) - DWORD formatc; // number of formats - const BASS_PLUGINFORM *formats; // the array of formats -} BASS_PLUGININFO; - -// 3D vector (for 3D positions/velocities/orientations) -typedef struct BASS_3DVECTOR { -#ifdef __cplusplus - BASS_3DVECTOR() {}; - BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; -#endif - float x; // +=right, -=left - float y; // +=up, -=down - float z; // +=front, -=behind -} BASS_3DVECTOR; - -// 3D channel modes -#define BASS_3DMODE_NORMAL 0 // normal 3D processing -#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener -#define BASS_3DMODE_OFF 2 // no 3D processing - -// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) -#define BASS_3DALG_DEFAULT 0 -#define BASS_3DALG_OFF 1 -#define BASS_3DALG_FULL 2 -#define BASS_3DALG_LIGHT 3 - -// EAX environments, use with BASS_SetEAXParameters -enum -{ - EAX_ENVIRONMENT_GENERIC, - EAX_ENVIRONMENT_PADDEDCELL, - EAX_ENVIRONMENT_ROOM, - EAX_ENVIRONMENT_BATHROOM, - EAX_ENVIRONMENT_LIVINGROOM, - EAX_ENVIRONMENT_STONEROOM, - EAX_ENVIRONMENT_AUDITORIUM, - EAX_ENVIRONMENT_CONCERTHALL, - EAX_ENVIRONMENT_CAVE, - EAX_ENVIRONMENT_ARENA, - EAX_ENVIRONMENT_HANGAR, - EAX_ENVIRONMENT_CARPETEDHALLWAY, - EAX_ENVIRONMENT_HALLWAY, - EAX_ENVIRONMENT_STONECORRIDOR, - EAX_ENVIRONMENT_ALLEY, - EAX_ENVIRONMENT_FOREST, - EAX_ENVIRONMENT_CITY, - EAX_ENVIRONMENT_MOUNTAINS, - EAX_ENVIRONMENT_QUARRY, - EAX_ENVIRONMENT_PLAIN, - EAX_ENVIRONMENT_PARKINGLOT, - EAX_ENVIRONMENT_SEWERPIPE, - EAX_ENVIRONMENT_UNDERWATER, - EAX_ENVIRONMENT_DRUGGED, - EAX_ENVIRONMENT_DIZZY, - EAX_ENVIRONMENT_PSYCHOTIC, - - EAX_ENVIRONMENT_COUNT // total number of environments -}; - -// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) -#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F -#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F -#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F -#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F -#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F -#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F -#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F -#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F -#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F -#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F -#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F -#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F -#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F -#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F -#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F -#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F -#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F -#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F -#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F -#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F -#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F -#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F -#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F -#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F -#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F -#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F - -typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); -/* User stream callback function. -handle : The stream that needs writing -buffer : Buffer to write the samples in -length : Number of bytes to write -user : The 'user' parameter value given when calling BASS_StreamCreate -RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end the stream. */ - -#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag - -// special STREAMPROCs -#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream -#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream -#define STREAMPROC_DEVICE (STREAMPROC*)-2 // device mix stream -#define STREAMPROC_DEVICE_3D (STREAMPROC*)-3 // device 3D mix stream - -// BASS_StreamCreateFileUser file systems -#define STREAMFILE_NOBUFFER 0 -#define STREAMFILE_BUFFER 1 -#define STREAMFILE_BUFFERPUSH 2 - -// User file stream callback functions -typedef void (CALLBACK FILECLOSEPROC)(void *user); -typedef QWORD (CALLBACK FILELENPROC)(void *user); -typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); -typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); - -typedef struct { - FILECLOSEPROC *close; - FILELENPROC *length; - FILEREADPROC *read; - FILESEEKPROC *seek; -} BASS_FILEPROCS; - -// BASS_StreamPutFileData options -#define BASS_FILEDATA_END 0 // end & close the file - -// BASS_StreamGetFilePosition modes -#define BASS_FILEPOS_CURRENT 0 -#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT -#define BASS_FILEPOS_DOWNLOAD 1 -#define BASS_FILEPOS_END 2 -#define BASS_FILEPOS_START 3 -#define BASS_FILEPOS_CONNECTED 4 -#define BASS_FILEPOS_BUFFER 5 -#define BASS_FILEPOS_SOCKET 6 -#define BASS_FILEPOS_ASYNCBUF 7 -#define BASS_FILEPOS_SIZE 8 -#define BASS_FILEPOS_BUFFERING 9 - -typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); -/* Internet stream download callback function. -buffer : Buffer containing the downloaded data... NULL=end of download -length : Number of bytes in the buffer -user : The 'user' parameter value given when calling BASS_StreamCreateURL */ - -// BASS_ChannelSetSync types -#define BASS_SYNC_POS 0 -#define BASS_SYNC_END 2 -#define BASS_SYNC_META 4 -#define BASS_SYNC_SLIDE 5 -#define BASS_SYNC_STALL 6 -#define BASS_SYNC_DOWNLOAD 7 -#define BASS_SYNC_FREE 8 -#define BASS_SYNC_SETPOS 11 -#define BASS_SYNC_MUSICPOS 10 -#define BASS_SYNC_MUSICINST 1 -#define BASS_SYNC_MUSICFX 3 -#define BASS_SYNC_OGG_CHANGE 12 -#define BASS_SYNC_DEV_FAIL 14 -#define BASS_SYNC_DEV_FORMAT 15 -#define BASS_SYNC_THREAD 0x20000000 // flag: call sync in other thread -#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime -#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously - -typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); -/* Sync callback function. -handle : The sync that has occured -channel: Channel that the sync occured in -data : Additional data associated with the sync's occurance -user : The 'user' parameter given when calling BASS_ChannelSetSync */ - -typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); -/* DSP callback function. -handle : The DSP handle -channel: Channel that the DSP is being applied to -buffer : Buffer to apply the DSP to -length : Number of bytes in the buffer -user : The 'user' parameter given when calling BASS_ChannelSetDSP */ - -typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); -/* Recording callback function. -handle : The recording handle -buffer : Buffer containing the recorded sample data -length : Number of bytes -user : The 'user' parameter value given when calling BASS_RecordStart -RETURN : TRUE = continue recording, FALSE = stop */ - -// BASS_ChannelIsActive return values -#define BASS_ACTIVE_STOPPED 0 -#define BASS_ACTIVE_PLAYING 1 -#define BASS_ACTIVE_STALLED 2 -#define BASS_ACTIVE_PAUSED 3 -#define BASS_ACTIVE_PAUSED_DEVICE 4 - -// Channel attributes -#define BASS_ATTRIB_FREQ 1 -#define BASS_ATTRIB_VOL 2 -#define BASS_ATTRIB_PAN 3 -#define BASS_ATTRIB_EAXMIX 4 -#define BASS_ATTRIB_NOBUFFER 5 -#define BASS_ATTRIB_VBR 6 -#define BASS_ATTRIB_CPU 7 -#define BASS_ATTRIB_SRC 8 -#define BASS_ATTRIB_NET_RESUME 9 -#define BASS_ATTRIB_SCANINFO 10 -#define BASS_ATTRIB_NORAMP 11 -#define BASS_ATTRIB_BITRATE 12 -#define BASS_ATTRIB_BUFFER 13 -#define BASS_ATTRIB_GRANULE 14 -#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 -#define BASS_ATTRIB_MUSIC_PANSEP 0x101 -#define BASS_ATTRIB_MUSIC_PSCALER 0x102 -#define BASS_ATTRIB_MUSIC_BPM 0x103 -#define BASS_ATTRIB_MUSIC_SPEED 0x104 -#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 -#define BASS_ATTRIB_MUSIC_ACTIVE 0x106 -#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # -#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # - -// BASS_ChannelSlideAttribute flags -#define BASS_SLIDE_LOG 0x1000000 - -// BASS_ChannelGetData flags -#define BASS_DATA_AVAILABLE 0 // query how much data is buffered -#define BASS_DATA_FIXED 0x20000000 // flag: return 8.24 fixed-point data -#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data -#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT -#define BASS_DATA_FFT512 0x80000001 // 512 FFT -#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT -#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT -#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT -#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT -#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT -#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT -#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined -#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window -#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias -#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data -#define BASS_DATA_FFT_NYQUIST 0x100 // FFT flag: return extra Nyquist value - -// BASS_ChannelGetLevelEx flags -#define BASS_LEVEL_MONO 1 -#define BASS_LEVEL_STEREO 2 -#define BASS_LEVEL_RMS 4 -#define BASS_LEVEL_VOLPAN 8 - -// BASS_ChannelGetTags types : what's returned -#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure -#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block -#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings -#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings -#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings -#define BASS_TAG_META 5 // ICY metadata : ANSI string -#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings -#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings -#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings -#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string -#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string -#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure -#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings -#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure -#define BASS_TAG_AM_MIME 15 // Android Media MIME type : ASCII string -#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string -#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings -#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure -#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure -#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string -#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure -#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure -#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure -#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string -#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string -#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers -#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string -#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string -#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string - -// ID3v1 tag structure -typedef struct { - char id[3]; - char title[30]; - char artist[30]; - char album[30]; - char year[4]; - char comment[30]; - BYTE genre; -} TAG_ID3; - -// Binary APE tag structure -typedef struct { - const char *key; - const void *data; - DWORD length; -} TAG_APE_BINARY; - -// BWF "bext" tag structure -#ifdef _MSC_VER -#pragma warning(push) -#pragma warning(disable:4200) -#endif -#pragma pack(push,1) -typedef struct { - char Description[256]; // description - char Originator[32]; // name of the originator - char OriginatorReference[32]; // reference of the originator - char OriginationDate[10]; // date of creation (yyyy-mm-dd) - char OriginationTime[8]; // time of creation (hh-mm-ss) - QWORD TimeReference; // first sample count since midnight (little-endian) - WORD Version; // BWF version (little-endian) - BYTE UMID[64]; // SMPTE UMID - BYTE Reserved[190]; -#if defined(__GNUC__) && __GNUC__<3 - char CodingHistory[0]; // history -#elif 1 // change to 0 if compiler fails the following line - char CodingHistory[]; // history -#else - char CodingHistory[1]; // history -#endif -} TAG_BEXT; -#pragma pack(pop) - -// BWF "cart" tag structures -typedef struct -{ - DWORD dwUsage; // FOURCC timer usage ID - DWORD dwValue; // timer value in samples from head -} TAG_CART_TIMER; - -typedef struct -{ - char Version[4]; // version of the data structure - char Title[64]; // title of cart audio sequence - char Artist[64]; // artist or creator name - char CutID[64]; // cut number identification - char ClientID[64]; // client identification - char Category[64]; // category ID, PSA, NEWS, etc - char Classification[64]; // classification or auxiliary key - char OutCue[64]; // out cue text - char StartDate[10]; // yyyy-mm-dd - char StartTime[8]; // hh:mm:ss - char EndDate[10]; // yyyy-mm-dd - char EndTime[8]; // hh:mm:ss - char ProducerAppID[64]; // name of vendor or application - char ProducerAppVersion[64]; // version of producer application - char UserDef[64]; // user defined text - DWORD dwLevelReference; // sample value for 0 dB reference - TAG_CART_TIMER PostTimer[8]; // 8 time markers after head - char Reserved[276]; - char URL[1024]; // uniform resource locator -#if defined(__GNUC__) && __GNUC__<3 - char TagText[0]; // free form text for scripts or tags -#elif 1 // change to 0 if compiler fails the following line - char TagText[]; // free form text for scripts or tags -#else - char TagText[1]; // free form text for scripts or tags -#endif -} TAG_CART; - -// RIFF "cue " tag structures -typedef struct -{ - DWORD dwName; - DWORD dwPosition; - DWORD fccChunk; - DWORD dwChunkStart; - DWORD dwBlockStart; - DWORD dwSampleOffset; -} TAG_CUE_POINT; - -typedef struct -{ - DWORD dwCuePoints; -#if defined(__GNUC__) && __GNUC__<3 - TAG_CUE_POINT CuePoints[0]; -#elif 1 // change to 0 if compiler fails the following line - TAG_CUE_POINT CuePoints[]; -#else - TAG_CUE_POINT CuePoints[1]; -#endif -} TAG_CUE; - -// RIFF "smpl" tag structures -typedef struct -{ - DWORD dwIdentifier; - DWORD dwType; - DWORD dwStart; - DWORD dwEnd; - DWORD dwFraction; - DWORD dwPlayCount; -} TAG_SMPL_LOOP; - -typedef struct -{ - DWORD dwManufacturer; - DWORD dwProduct; - DWORD dwSamplePeriod; - DWORD dwMIDIUnityNote; - DWORD dwMIDIPitchFraction; - DWORD dwSMPTEFormat; - DWORD dwSMPTEOffset; - DWORD cSampleLoops; - DWORD cbSamplerData; -#if defined(__GNUC__) && __GNUC__<3 - TAG_SMPL_LOOP SampleLoops[0]; -#elif 1 // change to 0 if compiler fails the following line - TAG_SMPL_LOOP SampleLoops[]; -#else - TAG_SMPL_LOOP SampleLoops[1]; -#endif -} TAG_SMPL; -#ifdef _MSC_VER -#pragma warning(pop) -#endif - -// CoreAudio codec info structure -typedef struct { - DWORD ftype; // file format - DWORD atype; // audio format - const char *name; // description -} TAG_CA_CODEC; - -#ifndef _WAVEFORMATEX_ -#define _WAVEFORMATEX_ -#pragma pack(push,1) -typedef struct tWAVEFORMATEX -{ - WORD wFormatTag; - WORD nChannels; - DWORD nSamplesPerSec; - DWORD nAvgBytesPerSec; - WORD nBlockAlign; - WORD wBitsPerSample; - WORD cbSize; -} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX; -typedef const WAVEFORMATEX *LPCWAVEFORMATEX; -#pragma pack(pop) -#endif - -// BASS_ChannelGetLength/GetPosition/SetPosition modes -#define BASS_POS_BYTE 0 // byte position -#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) -#define BASS_POS_OGG 3 // OGG bitstream number -#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers -#define BASS_POS_RELATIVE 0x4000000 // flag: seek relative to the current position -#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position -#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position -#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking -#define BASS_POS_SCAN 0x40000000 // flag: scan to the position - -// BASS_ChannelSetDevice/GetDevice option -#define BASS_NODEVICE 0x20000 - -// BASS_RecordSetInput flags -#define BASS_INPUT_OFF 0x10000 -#define BASS_INPUT_ON 0x20000 - -#define BASS_INPUT_TYPE_MASK 0xff000000 -#define BASS_INPUT_TYPE_UNDEF 0x00000000 -#define BASS_INPUT_TYPE_DIGITAL 0x01000000 -#define BASS_INPUT_TYPE_LINE 0x02000000 -#define BASS_INPUT_TYPE_MIC 0x03000000 -#define BASS_INPUT_TYPE_SYNTH 0x04000000 -#define BASS_INPUT_TYPE_CD 0x05000000 -#define BASS_INPUT_TYPE_PHONE 0x06000000 -#define BASS_INPUT_TYPE_SPEAKER 0x07000000 -#define BASS_INPUT_TYPE_WAVE 0x08000000 -#define BASS_INPUT_TYPE_AUX 0x09000000 -#define BASS_INPUT_TYPE_ANALOG 0x0a000000 - -// BASS_ChannelSetFX effect types -#define BASS_FX_DX8_CHORUS 0 -#define BASS_FX_DX8_COMPRESSOR 1 -#define BASS_FX_DX8_DISTORTION 2 -#define BASS_FX_DX8_ECHO 3 -#define BASS_FX_DX8_FLANGER 4 -#define BASS_FX_DX8_GARGLE 5 -#define BASS_FX_DX8_I3DL2REVERB 6 -#define BASS_FX_DX8_PARAMEQ 7 -#define BASS_FX_DX8_REVERB 8 -#define BASS_FX_VOLUME 9 - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_CHORUS; - -typedef struct { - float fGain; - float fAttack; - float fRelease; - float fThreshold; - float fRatio; - float fPredelay; -} BASS_DX8_COMPRESSOR; - -typedef struct { - float fGain; - float fEdge; - float fPostEQCenterFrequency; - float fPostEQBandwidth; - float fPreLowpassCutoff; -} BASS_DX8_DISTORTION; - -typedef struct { - float fWetDryMix; - float fFeedback; - float fLeftDelay; - float fRightDelay; - BOOL lPanDelay; -} BASS_DX8_ECHO; - -typedef struct { - float fWetDryMix; - float fDepth; - float fFeedback; - float fFrequency; - DWORD lWaveform; // 0=triangle, 1=sine - float fDelay; - DWORD lPhase; // BASS_DX8_PHASE_xxx -} BASS_DX8_FLANGER; - -typedef struct { - DWORD dwRateHz; // Rate of modulation in hz - DWORD dwWaveShape; // 0=triangle, 1=square -} BASS_DX8_GARGLE; - -typedef struct { - int lRoom; // [-10000, 0] default: -1000 mB - int lRoomHF; // [-10000, 0] default: 0 mB - float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 - float flDecayTime; // [0.1, 20.0] default: 1.49s - float flDecayHFRatio; // [0.1, 2.0] default: 0.83 - int lReflections; // [-10000, 1000] default: -2602 mB - float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s - int lReverb; // [-10000, 2000] default: 200 mB - float flReverbDelay; // [0.0, 0.1] default: 0.011 s - float flDiffusion; // [0.0, 100.0] default: 100.0 % - float flDensity; // [0.0, 100.0] default: 100.0 % - float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz -} BASS_DX8_I3DL2REVERB; - -typedef struct { - float fCenter; - float fBandwidth; - float fGain; -} BASS_DX8_PARAMEQ; - -typedef struct { - float fInGain; // [-96.0,0.0] default: 0.0 dB - float fReverbMix; // [-96.0,0.0] default: 0.0 db - float fReverbTime; // [0.001,3000.0] default: 1000.0 ms - float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 -} BASS_DX8_REVERB; - -#define BASS_DX8_PHASE_NEG_180 0 -#define BASS_DX8_PHASE_NEG_90 1 -#define BASS_DX8_PHASE_ZERO 2 -#define BASS_DX8_PHASE_90 3 -#define BASS_DX8_PHASE_180 4 - -typedef struct { - float fTarget; - float fCurrent; - float fTime; - DWORD lCurve; -} BASS_FX_VOLUME_PARAM; - -typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status); -/* iOS notification callback function. -status : The notification (BASS_IOSNOTIFY_xxx) */ - -#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started -#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended - -BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); -DWORD BASSDEF(BASS_GetConfig)(DWORD option); -BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value); -void *BASSDEF(BASS_GetConfigPtr)(DWORD option); -DWORD BASSDEF(BASS_GetVersion)(); -int BASSDEF(BASS_ErrorGetCode)(); -BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); -#else -BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); -#endif -BOOL BASSDEF(BASS_SetDevice)(DWORD device); -DWORD BASSDEF(BASS_GetDevice)(); -BOOL BASSDEF(BASS_Free)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -void *BASSDEF(BASS_GetDSoundObject)(DWORD object); -#endif -BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); -BOOL BASSDEF(BASS_Update)(DWORD length); -float BASSDEF(BASS_GetCPU)(); -BOOL BASSDEF(BASS_Start)(); -BOOL BASSDEF(BASS_Stop)(); -BOOL BASSDEF(BASS_Pause)(); -BOOL BASSDEF(BASS_IsStarted)(); -BOOL BASSDEF(BASS_SetVolume)(float volume); -float BASSDEF(BASS_GetVolume)(); - -HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); -BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); -const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); - -BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); -BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); -BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); -BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); -void BASSDEF(BASS_Apply3D)(); -#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) -BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); -BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); -#endif - -HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); -BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); - -HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); -HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); -BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); -BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); -BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); -BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); -BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); -HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); -DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); -BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); - -HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); -HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); -HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); -BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); -QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); -DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); -DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); - -BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); -BOOL BASSDEF(BASS_RecordInit)(int device); -BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); -DWORD BASSDEF(BASS_RecordGetDevice)(); -BOOL BASSDEF(BASS_RecordFree)(); -BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); -const char *BASSDEF(BASS_RecordGetInputName)(int input); -BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); -DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); -HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); - -double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); -QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); -DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); -DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); -BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); -const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); -DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); -BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); -BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); -BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); -BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); -BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); -BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); -BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); -BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); -BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); -BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); -DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); -BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); -BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); -BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); -BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); -QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); -BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); -QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); -DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); -BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length, DWORD flags); -DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); -HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); -BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); -HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); -BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); -BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); -BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); -HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); -BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); - -BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); -BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); -BOOL BASSDEF(BASS_FXReset)(HFX handle); -BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority); - -#ifdef __cplusplus -} - -#if defined(_WIN32) && !defined(NOBASSOVERLOADS) -static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags) -{ - return BASS_PluginLoad((const char*)file, flags|BASS_UNICODE); -} - -static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD flags, DWORD freq) -{ - return BASS_MusicLoad(mem, (const void*)file, offset, length, flags|BASS_UNICODE, freq); -} - -static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD max, DWORD flags) -{ - return BASS_SampleLoad(mem, (const void*)file, offset, length, max, flags|BASS_UNICODE); -} - -static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags) -{ - return BASS_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE); -} - -static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user) -{ - return BASS_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user); -} - -static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value) -{ - return BASS_SetConfigPtr(option|BASS_UNICODE, (const void*)value); -} -#endif -#endif - -#endif + +// BASS_Init flags +#define BASS_DEVICE_8BITS 1 // 8 bit +#define BASS_DEVICE_MONO 2 // mono +#define BASS_DEVICE_3D 4 // enable 3D functionality +#define BASS_DEVICE_16BITS 8 // limit output to 16 bit +#define BASS_DEVICE_LATENCY 0x100 // calculate device latency (BASS_INFO struct) +#define BASS_DEVICE_CPSPEAKERS 0x400 // detect speakers via Windows control panel +#define BASS_DEVICE_SPEAKERS 0x800 // force enabling of speaker assignment +#define BASS_DEVICE_NOSPEAKER 0x1000 // ignore speaker arrangement +#define BASS_DEVICE_DMIX 0x2000 // use ALSA "dmix" plugin +#define BASS_DEVICE_FREQ 0x4000 // set device sample rate +#define BASS_DEVICE_STEREO 0x8000 // limit output to stereo +#define BASS_DEVICE_HOG 0x10000 // hog/exclusive mode +#define BASS_DEVICE_AUDIOTRACK 0x20000 // use AudioTrack output +#define BASS_DEVICE_DSOUND 0x40000 // use DirectSound output + +// DirectSound interfaces (for use with BASS_GetDSoundObject) +#define BASS_OBJECT_DS 1 // IDirectSound +#define BASS_OBJECT_DS3DL 2 // IDirectSound3DListener + +// Device info structure +typedef struct { +#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) + const wchar_t *name; // description + const wchar_t *driver; // driver +#else + const char *name; // description + const char *driver; // driver +#endif + DWORD flags; +} BASS_DEVICEINFO; + +// BASS_DEVICEINFO flags +#define BASS_DEVICE_ENABLED 1 +#define BASS_DEVICE_DEFAULT 2 +#define BASS_DEVICE_INIT 4 +#define BASS_DEVICE_LOOPBACK 8 + +#define BASS_DEVICE_TYPE_MASK 0xff000000 +#define BASS_DEVICE_TYPE_NETWORK 0x01000000 +#define BASS_DEVICE_TYPE_SPEAKERS 0x02000000 +#define BASS_DEVICE_TYPE_LINE 0x03000000 +#define BASS_DEVICE_TYPE_HEADPHONES 0x04000000 +#define BASS_DEVICE_TYPE_MICROPHONE 0x05000000 +#define BASS_DEVICE_TYPE_HEADSET 0x06000000 +#define BASS_DEVICE_TYPE_HANDSET 0x07000000 +#define BASS_DEVICE_TYPE_DIGITAL 0x08000000 +#define BASS_DEVICE_TYPE_SPDIF 0x09000000 +#define BASS_DEVICE_TYPE_HDMI 0x0a000000 +#define BASS_DEVICE_TYPE_DISPLAYPORT 0x40000000 + +// BASS_GetDeviceInfo flags +#define BASS_DEVICES_AIRPLAY 0x1000000 + +typedef struct { + DWORD flags; // device capabilities (DSCAPS_xxx flags) + DWORD hwsize; // size of total device hardware memory + DWORD hwfree; // size of free device hardware memory + DWORD freesam; // number of free sample slots in the hardware + DWORD free3d; // number of free 3D sample slots in the hardware + DWORD minrate; // min sample rate supported by the hardware + DWORD maxrate; // max sample rate supported by the hardware + BOOL eax; // device supports EAX? (always FALSE if BASS_DEVICE_3D was not used) + DWORD minbuf; // recommended minimum buffer length in ms (requires BASS_DEVICE_LATENCY) + DWORD dsver; // DirectSound version + DWORD latency; // delay (in ms) before start of playback (requires BASS_DEVICE_LATENCY) + DWORD initflags; // BASS_Init "flags" parameter + DWORD speakers; // number of speakers available + DWORD freq; // current output rate +} BASS_INFO; + +// BASS_INFO flags (from DSOUND.H) +#define DSCAPS_CONTINUOUSRATE 0x00000010 // supports all sample rates between min/maxrate +#define DSCAPS_EMULDRIVER 0x00000020 // device does NOT have hardware DirectSound support +#define DSCAPS_CERTIFIED 0x00000040 // device driver has been certified by Microsoft +#define DSCAPS_SECONDARYMONO 0x00000100 // mono +#define DSCAPS_SECONDARYSTEREO 0x00000200 // stereo +#define DSCAPS_SECONDARY8BIT 0x00000400 // 8 bit +#define DSCAPS_SECONDARY16BIT 0x00000800 // 16 bit + +// Recording device info structure +typedef struct { + DWORD flags; // device capabilities (DSCCAPS_xxx flags) + DWORD formats; // supported standard formats (WAVE_FORMAT_xxx flags) + DWORD inputs; // number of inputs + BOOL singlein; // TRUE = only 1 input can be set at a time + DWORD freq; // current input rate +} BASS_RECORDINFO; + +// BASS_RECORDINFO flags (from DSOUND.H) +#define DSCCAPS_EMULDRIVER DSCAPS_EMULDRIVER // device does NOT have hardware DirectSound recording support +#define DSCCAPS_CERTIFIED DSCAPS_CERTIFIED // device driver has been certified by Microsoft + +// defines for formats field of BASS_RECORDINFO (from MMSYSTEM.H) +#ifndef WAVE_FORMAT_1M08 +#define WAVE_FORMAT_1M08 0x00000001 /* 11.025 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_1S08 0x00000002 /* 11.025 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_1M16 0x00000004 /* 11.025 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_1S16 0x00000008 /* 11.025 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_2M08 0x00000010 /* 22.05 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_2S08 0x00000020 /* 22.05 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_2M16 0x00000040 /* 22.05 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_2S16 0x00000080 /* 22.05 kHz, Stereo, 16-bit */ +#define WAVE_FORMAT_4M08 0x00000100 /* 44.1 kHz, Mono, 8-bit */ +#define WAVE_FORMAT_4S08 0x00000200 /* 44.1 kHz, Stereo, 8-bit */ +#define WAVE_FORMAT_4M16 0x00000400 /* 44.1 kHz, Mono, 16-bit */ +#define WAVE_FORMAT_4S16 0x00000800 /* 44.1 kHz, Stereo, 16-bit */ +#endif + +// Sample info structure +typedef struct { + DWORD freq; // default playback rate + float volume; // default volume (0-1) + float pan; // default pan (-1=left, 0=middle, 1=right) + DWORD flags; // BASS_SAMPLE_xxx flags + DWORD length; // length (in bytes) + DWORD max; // maximum simultaneous playbacks + DWORD origres; // original resolution + DWORD chans; // number of channels + DWORD mingap; // minimum gap (ms) between creating channels + DWORD mode3d; // BASS_3DMODE_xxx mode + float mindist; // minimum distance + float maxdist; // maximum distance + DWORD iangle; // angle of inside projection cone + DWORD oangle; // angle of outside projection cone + float outvol; // delta-volume outside the projection cone + DWORD vam; // voice allocation/management flags (BASS_VAM_xxx) + DWORD priority; // priority (0=lowest, 0xffffffff=highest) +} BASS_SAMPLE; + +#define BASS_SAMPLE_8BITS 1 // 8 bit +#define BASS_SAMPLE_FLOAT 256 // 32 bit floating-point +#define BASS_SAMPLE_MONO 2 // mono +#define BASS_SAMPLE_LOOP 4 // looped +#define BASS_SAMPLE_3D 8 // 3D functionality +#define BASS_SAMPLE_SOFTWARE 16 // not using hardware mixing +#define BASS_SAMPLE_MUTEMAX 32 // mute at max distance (3D only) +#define BASS_SAMPLE_VAM 64 // DX7 voice allocation & management +#define BASS_SAMPLE_FX 128 // old implementation of DX8 effects +#define BASS_SAMPLE_OVER_VOL 0x10000 // override lowest volume +#define BASS_SAMPLE_OVER_POS 0x20000 // override longest playing +#define BASS_SAMPLE_OVER_DIST 0x30000 // override furthest from listener (3D only) + +#define BASS_STREAM_PRESCAN 0x20000 // enable pin-point seeking/length (MP3/MP2/MP1) +#define BASS_STREAM_AUTOFREE 0x40000 // automatically free the stream when it stop/ends +#define BASS_STREAM_RESTRATE 0x80000 // restrict the download rate of internet file streams +#define BASS_STREAM_BLOCK 0x100000 // download/play internet file stream in small blocks +#define BASS_STREAM_DECODE 0x200000 // don't play the stream, only decode (BASS_ChannelGetData) +#define BASS_STREAM_STATUS 0x800000 // give server status info (HTTP/ICY tags) in DOWNLOADPROC + +#define BASS_MP3_IGNOREDELAY 0x200 // ignore LAME/Xing/VBRI/iTunes delay & padding info +#define BASS_MP3_SETPOS BASS_STREAM_PRESCAN + +#define BASS_MUSIC_FLOAT BASS_SAMPLE_FLOAT +#define BASS_MUSIC_MONO BASS_SAMPLE_MONO +#define BASS_MUSIC_LOOP BASS_SAMPLE_LOOP +#define BASS_MUSIC_3D BASS_SAMPLE_3D +#define BASS_MUSIC_FX BASS_SAMPLE_FX +#define BASS_MUSIC_AUTOFREE BASS_STREAM_AUTOFREE +#define BASS_MUSIC_DECODE BASS_STREAM_DECODE +#define BASS_MUSIC_PRESCAN BASS_STREAM_PRESCAN // calculate playback length +#define BASS_MUSIC_CALCLEN BASS_MUSIC_PRESCAN +#define BASS_MUSIC_RAMP 0x200 // normal ramping +#define BASS_MUSIC_RAMPS 0x400 // sensitive ramping +#define BASS_MUSIC_SURROUND 0x800 // surround sound +#define BASS_MUSIC_SURROUND2 0x1000 // surround sound (mode 2) +#define BASS_MUSIC_FT2PAN 0x2000 // apply FastTracker 2 panning to XM files +#define BASS_MUSIC_FT2MOD 0x2000 // play .MOD as FastTracker 2 does +#define BASS_MUSIC_PT1MOD 0x4000 // play .MOD as ProTracker 1 does +#define BASS_MUSIC_NONINTER 0x10000 // non-interpolated sample mixing +#define BASS_MUSIC_SINCINTER 0x800000 // sinc interpolated sample mixing +#define BASS_MUSIC_POSRESET 0x8000 // stop all notes when moving position +#define BASS_MUSIC_POSRESETEX 0x400000 // stop all notes and reset bmp/etc when moving position +#define BASS_MUSIC_STOPBACK 0x80000 // stop the music on a backwards jump effect +#define BASS_MUSIC_NOSAMPLE 0x100000 // don't load the samples + +// Speaker assignment flags +#define BASS_SPEAKER_FRONT 0x1000000 // front speakers +#define BASS_SPEAKER_REAR 0x2000000 // rear/side speakers +#define BASS_SPEAKER_CENLFE 0x3000000 // center & LFE speakers (5.1) +#define BASS_SPEAKER_REAR2 0x4000000 // rear center speakers (7.1) +#define BASS_SPEAKER_N(n) ((n)<<24) // n'th pair of speakers (max 15) +#define BASS_SPEAKER_LEFT 0x10000000 // modifier: left +#define BASS_SPEAKER_RIGHT 0x20000000 // modifier: right +#define BASS_SPEAKER_FRONTLEFT BASS_SPEAKER_FRONT|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_FRONTRIGHT BASS_SPEAKER_FRONT|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REARLEFT BASS_SPEAKER_REAR|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REARRIGHT BASS_SPEAKER_REAR|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_CENTER BASS_SPEAKER_CENLFE|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_LFE BASS_SPEAKER_CENLFE|BASS_SPEAKER_RIGHT +#define BASS_SPEAKER_REAR2LEFT BASS_SPEAKER_REAR2|BASS_SPEAKER_LEFT +#define BASS_SPEAKER_REAR2RIGHT BASS_SPEAKER_REAR2|BASS_SPEAKER_RIGHT + +#define BASS_ASYNCFILE 0x40000000 +#define BASS_UNICODE 0x80000000 + +#define BASS_RECORD_PAUSE 0x8000 // start recording paused +#define BASS_RECORD_ECHOCANCEL 0x2000 +#define BASS_RECORD_AGC 0x4000 + +// DX7 voice allocation & management flags +#define BASS_VAM_HARDWARE 1 +#define BASS_VAM_SOFTWARE 2 +#define BASS_VAM_TERM_TIME 4 +#define BASS_VAM_TERM_DIST 8 +#define BASS_VAM_TERM_PRIO 16 + +// Channel info structure +typedef struct { + DWORD freq; // default playback rate + DWORD chans; // channels + DWORD flags; // BASS_SAMPLE/STREAM/MUSIC/SPEAKER flags + DWORD ctype; // type of channel + DWORD origres; // original resolution + HPLUGIN plugin; // plugin + HSAMPLE sample; // sample + const char *filename; // filename +} BASS_CHANNELINFO; + +#define BASS_ORIGRES_FLOAT 0x10000 + +// BASS_CHANNELINFO types +#define BASS_CTYPE_SAMPLE 1 +#define BASS_CTYPE_RECORD 2 +#define BASS_CTYPE_STREAM 0x10000 +#define BASS_CTYPE_STREAM_VORBIS 0x10002 +#define BASS_CTYPE_STREAM_OGG 0x10002 +#define BASS_CTYPE_STREAM_MP1 0x10003 +#define BASS_CTYPE_STREAM_MP2 0x10004 +#define BASS_CTYPE_STREAM_MP3 0x10005 +#define BASS_CTYPE_STREAM_AIFF 0x10006 +#define BASS_CTYPE_STREAM_CA 0x10007 +#define BASS_CTYPE_STREAM_MF 0x10008 +#define BASS_CTYPE_STREAM_AM 0x10009 +#define BASS_CTYPE_STREAM_DUMMY 0x18000 +#define BASS_CTYPE_STREAM_DEVICE 0x18001 +#define BASS_CTYPE_STREAM_WAV 0x40000 // WAVE flag, LOWORD=codec +#define BASS_CTYPE_STREAM_WAV_PCM 0x50001 +#define BASS_CTYPE_STREAM_WAV_FLOAT 0x50003 +#define BASS_CTYPE_MUSIC_MOD 0x20000 +#define BASS_CTYPE_MUSIC_MTM 0x20001 +#define BASS_CTYPE_MUSIC_S3M 0x20002 +#define BASS_CTYPE_MUSIC_XM 0x20003 +#define BASS_CTYPE_MUSIC_IT 0x20004 +#define BASS_CTYPE_MUSIC_MO3 0x00100 // MO3 flag + +typedef struct { + DWORD ctype; // channel type +#if defined(_WIN32_WCE) || (WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) + const wchar_t *name; // format description + const wchar_t *exts; // file extension filter (*.ext1;*.ext2;etc...) +#else + const char *name; // format description + const char *exts; // file extension filter (*.ext1;*.ext2;etc...) +#endif +} BASS_PLUGINFORM; + +typedef struct { + DWORD version; // version (same form as BASS_GetVersion) + DWORD formatc; // number of formats + const BASS_PLUGINFORM *formats; // the array of formats +} BASS_PLUGININFO; + +// 3D vector (for 3D positions/velocities/orientations) +typedef struct BASS_3DVECTOR { +#ifdef __cplusplus + BASS_3DVECTOR() {}; + BASS_3DVECTOR(float _x, float _y, float _z) : x(_x), y(_y), z(_z) {}; +#endif + float x; // +=right, -=left + float y; // +=up, -=down + float z; // +=front, -=behind +} BASS_3DVECTOR; + +// 3D channel modes +#define BASS_3DMODE_NORMAL 0 // normal 3D processing +#define BASS_3DMODE_RELATIVE 1 // position is relative to the listener +#define BASS_3DMODE_OFF 2 // no 3D processing + +// software 3D mixing algorithms (used with BASS_CONFIG_3DALGORITHM) +#define BASS_3DALG_DEFAULT 0 +#define BASS_3DALG_OFF 1 +#define BASS_3DALG_FULL 2 +#define BASS_3DALG_LIGHT 3 + +// EAX environments, use with BASS_SetEAXParameters +enum +{ + EAX_ENVIRONMENT_GENERIC, + EAX_ENVIRONMENT_PADDEDCELL, + EAX_ENVIRONMENT_ROOM, + EAX_ENVIRONMENT_BATHROOM, + EAX_ENVIRONMENT_LIVINGROOM, + EAX_ENVIRONMENT_STONEROOM, + EAX_ENVIRONMENT_AUDITORIUM, + EAX_ENVIRONMENT_CONCERTHALL, + EAX_ENVIRONMENT_CAVE, + EAX_ENVIRONMENT_ARENA, + EAX_ENVIRONMENT_HANGAR, + EAX_ENVIRONMENT_CARPETEDHALLWAY, + EAX_ENVIRONMENT_HALLWAY, + EAX_ENVIRONMENT_STONECORRIDOR, + EAX_ENVIRONMENT_ALLEY, + EAX_ENVIRONMENT_FOREST, + EAX_ENVIRONMENT_CITY, + EAX_ENVIRONMENT_MOUNTAINS, + EAX_ENVIRONMENT_QUARRY, + EAX_ENVIRONMENT_PLAIN, + EAX_ENVIRONMENT_PARKINGLOT, + EAX_ENVIRONMENT_SEWERPIPE, + EAX_ENVIRONMENT_UNDERWATER, + EAX_ENVIRONMENT_DRUGGED, + EAX_ENVIRONMENT_DIZZY, + EAX_ENVIRONMENT_PSYCHOTIC, + + EAX_ENVIRONMENT_COUNT // total number of environments +}; + +// EAX presets, usage: BASS_SetEAXParameters(EAX_PRESET_xxx) +#define EAX_PRESET_GENERIC EAX_ENVIRONMENT_GENERIC,0.5F,1.493F,0.5F +#define EAX_PRESET_PADDEDCELL EAX_ENVIRONMENT_PADDEDCELL,0.25F,0.1F,0.0F +#define EAX_PRESET_ROOM EAX_ENVIRONMENT_ROOM,0.417F,0.4F,0.666F +#define EAX_PRESET_BATHROOM EAX_ENVIRONMENT_BATHROOM,0.653F,1.499F,0.166F +#define EAX_PRESET_LIVINGROOM EAX_ENVIRONMENT_LIVINGROOM,0.208F,0.478F,0.0F +#define EAX_PRESET_STONEROOM EAX_ENVIRONMENT_STONEROOM,0.5F,2.309F,0.888F +#define EAX_PRESET_AUDITORIUM EAX_ENVIRONMENT_AUDITORIUM,0.403F,4.279F,0.5F +#define EAX_PRESET_CONCERTHALL EAX_ENVIRONMENT_CONCERTHALL,0.5F,3.961F,0.5F +#define EAX_PRESET_CAVE EAX_ENVIRONMENT_CAVE,0.5F,2.886F,1.304F +#define EAX_PRESET_ARENA EAX_ENVIRONMENT_ARENA,0.361F,7.284F,0.332F +#define EAX_PRESET_HANGAR EAX_ENVIRONMENT_HANGAR,0.5F,10.0F,0.3F +#define EAX_PRESET_CARPETEDHALLWAY EAX_ENVIRONMENT_CARPETEDHALLWAY,0.153F,0.259F,2.0F +#define EAX_PRESET_HALLWAY EAX_ENVIRONMENT_HALLWAY,0.361F,1.493F,0.0F +#define EAX_PRESET_STONECORRIDOR EAX_ENVIRONMENT_STONECORRIDOR,0.444F,2.697F,0.638F +#define EAX_PRESET_ALLEY EAX_ENVIRONMENT_ALLEY,0.25F,1.752F,0.776F +#define EAX_PRESET_FOREST EAX_ENVIRONMENT_FOREST,0.111F,3.145F,0.472F +#define EAX_PRESET_CITY EAX_ENVIRONMENT_CITY,0.111F,2.767F,0.224F +#define EAX_PRESET_MOUNTAINS EAX_ENVIRONMENT_MOUNTAINS,0.194F,7.841F,0.472F +#define EAX_PRESET_QUARRY EAX_ENVIRONMENT_QUARRY,1.0F,1.499F,0.5F +#define EAX_PRESET_PLAIN EAX_ENVIRONMENT_PLAIN,0.097F,2.767F,0.224F +#define EAX_PRESET_PARKINGLOT EAX_ENVIRONMENT_PARKINGLOT,0.208F,1.652F,1.5F +#define EAX_PRESET_SEWERPIPE EAX_ENVIRONMENT_SEWERPIPE,0.652F,2.886F,0.25F +#define EAX_PRESET_UNDERWATER EAX_ENVIRONMENT_UNDERWATER,1.0F,1.499F,0.0F +#define EAX_PRESET_DRUGGED EAX_ENVIRONMENT_DRUGGED,0.875F,8.392F,1.388F +#define EAX_PRESET_DIZZY EAX_ENVIRONMENT_DIZZY,0.139F,17.234F,0.666F +#define EAX_PRESET_PSYCHOTIC EAX_ENVIRONMENT_PSYCHOTIC,0.486F,7.563F,0.806F + +typedef DWORD (CALLBACK STREAMPROC)(HSTREAM handle, void *buffer, DWORD length, void *user); +/* User stream callback function. +handle : The stream that needs writing +buffer : Buffer to write the samples in +length : Number of bytes to write +user : The 'user' parameter value given when calling BASS_StreamCreate +RETURN : Number of bytes written. Set the BASS_STREAMPROC_END flag to end the stream. */ + +#define BASS_STREAMPROC_END 0x80000000 // end of user stream flag + +// special STREAMPROCs +#define STREAMPROC_DUMMY (STREAMPROC*)0 // "dummy" stream +#define STREAMPROC_PUSH (STREAMPROC*)-1 // push stream +#define STREAMPROC_DEVICE (STREAMPROC*)-2 // device mix stream +#define STREAMPROC_DEVICE_3D (STREAMPROC*)-3 // device 3D mix stream + +// BASS_StreamCreateFileUser file systems +#define STREAMFILE_NOBUFFER 0 +#define STREAMFILE_BUFFER 1 +#define STREAMFILE_BUFFERPUSH 2 + +// User file stream callback functions +typedef void (CALLBACK FILECLOSEPROC)(void *user); +typedef QWORD (CALLBACK FILELENPROC)(void *user); +typedef DWORD (CALLBACK FILEREADPROC)(void *buffer, DWORD length, void *user); +typedef BOOL (CALLBACK FILESEEKPROC)(QWORD offset, void *user); + +typedef struct { + FILECLOSEPROC *close; + FILELENPROC *length; + FILEREADPROC *read; + FILESEEKPROC *seek; +} BASS_FILEPROCS; + +// BASS_StreamPutFileData options +#define BASS_FILEDATA_END 0 // end & close the file + +// BASS_StreamGetFilePosition modes +#define BASS_FILEPOS_CURRENT 0 +#define BASS_FILEPOS_DECODE BASS_FILEPOS_CURRENT +#define BASS_FILEPOS_DOWNLOAD 1 +#define BASS_FILEPOS_END 2 +#define BASS_FILEPOS_START 3 +#define BASS_FILEPOS_CONNECTED 4 +#define BASS_FILEPOS_BUFFER 5 +#define BASS_FILEPOS_SOCKET 6 +#define BASS_FILEPOS_ASYNCBUF 7 +#define BASS_FILEPOS_SIZE 8 +#define BASS_FILEPOS_BUFFERING 9 + +typedef void (CALLBACK DOWNLOADPROC)(const void *buffer, DWORD length, void *user); +/* Internet stream download callback function. +buffer : Buffer containing the downloaded data... NULL=end of download +length : Number of bytes in the buffer +user : The 'user' parameter value given when calling BASS_StreamCreateURL */ + +// BASS_ChannelSetSync types +#define BASS_SYNC_POS 0 +#define BASS_SYNC_END 2 +#define BASS_SYNC_META 4 +#define BASS_SYNC_SLIDE 5 +#define BASS_SYNC_STALL 6 +#define BASS_SYNC_DOWNLOAD 7 +#define BASS_SYNC_FREE 8 +#define BASS_SYNC_SETPOS 11 +#define BASS_SYNC_MUSICPOS 10 +#define BASS_SYNC_MUSICINST 1 +#define BASS_SYNC_MUSICFX 3 +#define BASS_SYNC_OGG_CHANGE 12 +#define BASS_SYNC_DEV_FAIL 14 +#define BASS_SYNC_DEV_FORMAT 15 +#define BASS_SYNC_THREAD 0x20000000 // flag: call sync in other thread +#define BASS_SYNC_MIXTIME 0x40000000 // flag: sync at mixtime, else at playtime +#define BASS_SYNC_ONETIME 0x80000000 // flag: sync only once, else continuously + +typedef void (CALLBACK SYNCPROC)(HSYNC handle, DWORD channel, DWORD data, void *user); +/* Sync callback function. +handle : The sync that has occured +channel: Channel that the sync occured in +data : Additional data associated with the sync's occurance +user : The 'user' parameter given when calling BASS_ChannelSetSync */ + +typedef void (CALLBACK DSPPROC)(HDSP handle, DWORD channel, void *buffer, DWORD length, void *user); +/* DSP callback function. +handle : The DSP handle +channel: Channel that the DSP is being applied to +buffer : Buffer to apply the DSP to +length : Number of bytes in the buffer +user : The 'user' parameter given when calling BASS_ChannelSetDSP */ + +typedef BOOL (CALLBACK RECORDPROC)(HRECORD handle, const void *buffer, DWORD length, void *user); +/* Recording callback function. +handle : The recording handle +buffer : Buffer containing the recorded sample data +length : Number of bytes +user : The 'user' parameter value given when calling BASS_RecordStart +RETURN : TRUE = continue recording, FALSE = stop */ + +// BASS_ChannelIsActive return values +#define BASS_ACTIVE_STOPPED 0 +#define BASS_ACTIVE_PLAYING 1 +#define BASS_ACTIVE_STALLED 2 +#define BASS_ACTIVE_PAUSED 3 +#define BASS_ACTIVE_PAUSED_DEVICE 4 + +// Channel attributes +#define BASS_ATTRIB_FREQ 1 +#define BASS_ATTRIB_VOL 2 +#define BASS_ATTRIB_PAN 3 +#define BASS_ATTRIB_EAXMIX 4 +#define BASS_ATTRIB_NOBUFFER 5 +#define BASS_ATTRIB_VBR 6 +#define BASS_ATTRIB_CPU 7 +#define BASS_ATTRIB_SRC 8 +#define BASS_ATTRIB_NET_RESUME 9 +#define BASS_ATTRIB_SCANINFO 10 +#define BASS_ATTRIB_NORAMP 11 +#define BASS_ATTRIB_BITRATE 12 +#define BASS_ATTRIB_BUFFER 13 +#define BASS_ATTRIB_GRANULE 14 +#define BASS_ATTRIB_MUSIC_AMPLIFY 0x100 +#define BASS_ATTRIB_MUSIC_PANSEP 0x101 +#define BASS_ATTRIB_MUSIC_PSCALER 0x102 +#define BASS_ATTRIB_MUSIC_BPM 0x103 +#define BASS_ATTRIB_MUSIC_SPEED 0x104 +#define BASS_ATTRIB_MUSIC_VOL_GLOBAL 0x105 +#define BASS_ATTRIB_MUSIC_ACTIVE 0x106 +#define BASS_ATTRIB_MUSIC_VOL_CHAN 0x200 // + channel # +#define BASS_ATTRIB_MUSIC_VOL_INST 0x300 // + instrument # + +// BASS_ChannelSlideAttribute flags +#define BASS_SLIDE_LOG 0x1000000 + +// BASS_ChannelGetData flags +#define BASS_DATA_AVAILABLE 0 // query how much data is buffered +#define BASS_DATA_FIXED 0x20000000 // flag: return 8.24 fixed-point data +#define BASS_DATA_FLOAT 0x40000000 // flag: return floating-point sample data +#define BASS_DATA_FFT256 0x80000000 // 256 sample FFT +#define BASS_DATA_FFT512 0x80000001 // 512 FFT +#define BASS_DATA_FFT1024 0x80000002 // 1024 FFT +#define BASS_DATA_FFT2048 0x80000003 // 2048 FFT +#define BASS_DATA_FFT4096 0x80000004 // 4096 FFT +#define BASS_DATA_FFT8192 0x80000005 // 8192 FFT +#define BASS_DATA_FFT16384 0x80000006 // 16384 FFT +#define BASS_DATA_FFT32768 0x80000007 // 32768 FFT +#define BASS_DATA_FFT_INDIVIDUAL 0x10 // FFT flag: FFT for each channel, else all combined +#define BASS_DATA_FFT_NOWINDOW 0x20 // FFT flag: no Hanning window +#define BASS_DATA_FFT_REMOVEDC 0x40 // FFT flag: pre-remove DC bias +#define BASS_DATA_FFT_COMPLEX 0x80 // FFT flag: return complex data +#define BASS_DATA_FFT_NYQUIST 0x100 // FFT flag: return extra Nyquist value + +// BASS_ChannelGetLevelEx flags +#define BASS_LEVEL_MONO 1 +#define BASS_LEVEL_STEREO 2 +#define BASS_LEVEL_RMS 4 +#define BASS_LEVEL_VOLPAN 8 + +// BASS_ChannelGetTags types : what's returned +#define BASS_TAG_ID3 0 // ID3v1 tags : TAG_ID3 structure +#define BASS_TAG_ID3V2 1 // ID3v2 tags : variable length block +#define BASS_TAG_OGG 2 // OGG comments : series of null-terminated UTF-8 strings +#define BASS_TAG_HTTP 3 // HTTP headers : series of null-terminated ANSI strings +#define BASS_TAG_ICY 4 // ICY headers : series of null-terminated ANSI strings +#define BASS_TAG_META 5 // ICY metadata : ANSI string +#define BASS_TAG_APE 6 // APE tags : series of null-terminated UTF-8 strings +#define BASS_TAG_MP4 7 // MP4/iTunes metadata : series of null-terminated UTF-8 strings +#define BASS_TAG_WMA 8 // WMA tags : series of null-terminated UTF-8 strings +#define BASS_TAG_VENDOR 9 // OGG encoder : UTF-8 string +#define BASS_TAG_LYRICS3 10 // Lyric3v2 tag : ASCII string +#define BASS_TAG_CA_CODEC 11 // CoreAudio codec info : TAG_CA_CODEC structure +#define BASS_TAG_MF 13 // Media Foundation tags : series of null-terminated UTF-8 strings +#define BASS_TAG_WAVEFORMAT 14 // WAVE format : WAVEFORMATEEX structure +#define BASS_TAG_AM_MIME 15 // Android Media MIME type : ASCII string +#define BASS_TAG_AM_NAME 16 // Android Media codec name : ASCII string +#define BASS_TAG_RIFF_INFO 0x100 // RIFF "INFO" tags : series of null-terminated ANSI strings +#define BASS_TAG_RIFF_BEXT 0x101 // RIFF/BWF "bext" tags : TAG_BEXT structure +#define BASS_TAG_RIFF_CART 0x102 // RIFF/BWF "cart" tags : TAG_CART structure +#define BASS_TAG_RIFF_DISP 0x103 // RIFF "DISP" text tag : ANSI string +#define BASS_TAG_RIFF_CUE 0x104 // RIFF "cue " chunk : TAG_CUE structure +#define BASS_TAG_RIFF_SMPL 0x105 // RIFF "smpl" chunk : TAG_SMPL structure +#define BASS_TAG_APE_BINARY 0x1000 // + index #, binary APE tag : TAG_APE_BINARY structure +#define BASS_TAG_MUSIC_NAME 0x10000 // MOD music name : ANSI string +#define BASS_TAG_MUSIC_MESSAGE 0x10001 // MOD message : ANSI string +#define BASS_TAG_MUSIC_ORDERS 0x10002 // MOD order list : BYTE array of pattern numbers +#define BASS_TAG_MUSIC_AUTH 0x10003 // MOD author : UTF-8 string +#define BASS_TAG_MUSIC_INST 0x10100 // + instrument #, MOD instrument name : ANSI string +#define BASS_TAG_MUSIC_SAMPLE 0x10300 // + sample #, MOD sample name : ANSI string + +// ID3v1 tag structure +typedef struct { + char id[3]; + char title[30]; + char artist[30]; + char album[30]; + char year[4]; + char comment[30]; + BYTE genre; +} TAG_ID3; + +// Binary APE tag structure +typedef struct { + const char *key; + const void *data; + DWORD length; +} TAG_APE_BINARY; + +// BWF "bext" tag structure +#ifdef _MSC_VER +#pragma warning(push) +#pragma warning(disable:4200) +#endif +#pragma pack(push,1) +typedef struct { + char Description[256]; // description + char Originator[32]; // name of the originator + char OriginatorReference[32]; // reference of the originator + char OriginationDate[10]; // date of creation (yyyy-mm-dd) + char OriginationTime[8]; // time of creation (hh-mm-ss) + QWORD TimeReference; // first sample count since midnight (little-endian) + WORD Version; // BWF version (little-endian) + BYTE UMID[64]; // SMPTE UMID + BYTE Reserved[190]; +#if defined(__GNUC__) && __GNUC__<3 + char CodingHistory[0]; // history +#elif 1 // change to 0 if compiler fails the following line + char CodingHistory[]; // history +#else + char CodingHistory[1]; // history +#endif +} TAG_BEXT; +#pragma pack(pop) + +// BWF "cart" tag structures +typedef struct +{ + DWORD dwUsage; // FOURCC timer usage ID + DWORD dwValue; // timer value in samples from head +} TAG_CART_TIMER; + +typedef struct +{ + char Version[4]; // version of the data structure + char Title[64]; // title of cart audio sequence + char Artist[64]; // artist or creator name + char CutID[64]; // cut number identification + char ClientID[64]; // client identification + char Category[64]; // category ID, PSA, NEWS, etc + char Classification[64]; // classification or auxiliary key + char OutCue[64]; // out cue text + char StartDate[10]; // yyyy-mm-dd + char StartTime[8]; // hh:mm:ss + char EndDate[10]; // yyyy-mm-dd + char EndTime[8]; // hh:mm:ss + char ProducerAppID[64]; // name of vendor or application + char ProducerAppVersion[64]; // version of producer application + char UserDef[64]; // user defined text + DWORD dwLevelReference; // sample value for 0 dB reference + TAG_CART_TIMER PostTimer[8]; // 8 time markers after head + char Reserved[276]; + char URL[1024]; // uniform resource locator +#if defined(__GNUC__) && __GNUC__<3 + char TagText[0]; // free form text for scripts or tags +#elif 1 // change to 0 if compiler fails the following line + char TagText[]; // free form text for scripts or tags +#else + char TagText[1]; // free form text for scripts or tags +#endif +} TAG_CART; + +// RIFF "cue " tag structures +typedef struct +{ + DWORD dwName; + DWORD dwPosition; + DWORD fccChunk; + DWORD dwChunkStart; + DWORD dwBlockStart; + DWORD dwSampleOffset; +} TAG_CUE_POINT; + +typedef struct +{ + DWORD dwCuePoints; +#if defined(__GNUC__) && __GNUC__<3 + TAG_CUE_POINT CuePoints[0]; +#elif 1 // change to 0 if compiler fails the following line + TAG_CUE_POINT CuePoints[]; +#else + TAG_CUE_POINT CuePoints[1]; +#endif +} TAG_CUE; + +// RIFF "smpl" tag structures +typedef struct +{ + DWORD dwIdentifier; + DWORD dwType; + DWORD dwStart; + DWORD dwEnd; + DWORD dwFraction; + DWORD dwPlayCount; +} TAG_SMPL_LOOP; + +typedef struct +{ + DWORD dwManufacturer; + DWORD dwProduct; + DWORD dwSamplePeriod; + DWORD dwMIDIUnityNote; + DWORD dwMIDIPitchFraction; + DWORD dwSMPTEFormat; + DWORD dwSMPTEOffset; + DWORD cSampleLoops; + DWORD cbSamplerData; +#if defined(__GNUC__) && __GNUC__<3 + TAG_SMPL_LOOP SampleLoops[0]; +#elif 1 // change to 0 if compiler fails the following line + TAG_SMPL_LOOP SampleLoops[]; +#else + TAG_SMPL_LOOP SampleLoops[1]; +#endif +} TAG_SMPL; +#ifdef _MSC_VER +#pragma warning(pop) +#endif + +// CoreAudio codec info structure +typedef struct { + DWORD ftype; // file format + DWORD atype; // audio format + const char *name; // description +} TAG_CA_CODEC; + +#ifndef _WAVEFORMATEX_ +#define _WAVEFORMATEX_ +#pragma pack(push,1) +typedef struct tWAVEFORMATEX +{ + WORD wFormatTag; + WORD nChannels; + DWORD nSamplesPerSec; + DWORD nAvgBytesPerSec; + WORD nBlockAlign; + WORD wBitsPerSample; + WORD cbSize; +} WAVEFORMATEX, *PWAVEFORMATEX, *LPWAVEFORMATEX; +typedef const WAVEFORMATEX *LPCWAVEFORMATEX; +#pragma pack(pop) +#endif + +// BASS_ChannelGetLength/GetPosition/SetPosition modes +#define BASS_POS_BYTE 0 // byte position +#define BASS_POS_MUSIC_ORDER 1 // order.row position, MAKELONG(order,row) +#define BASS_POS_OGG 3 // OGG bitstream number +#define BASS_POS_RESET 0x2000000 // flag: reset user file buffers +#define BASS_POS_RELATIVE 0x4000000 // flag: seek relative to the current position +#define BASS_POS_INEXACT 0x8000000 // flag: allow seeking to inexact position +#define BASS_POS_DECODE 0x10000000 // flag: get the decoding (not playing) position +#define BASS_POS_DECODETO 0x20000000 // flag: decode to the position instead of seeking +#define BASS_POS_SCAN 0x40000000 // flag: scan to the position + +// BASS_ChannelSetDevice/GetDevice option +#define BASS_NODEVICE 0x20000 + +// BASS_RecordSetInput flags +#define BASS_INPUT_OFF 0x10000 +#define BASS_INPUT_ON 0x20000 + +#define BASS_INPUT_TYPE_MASK 0xff000000 +#define BASS_INPUT_TYPE_UNDEF 0x00000000 +#define BASS_INPUT_TYPE_DIGITAL 0x01000000 +#define BASS_INPUT_TYPE_LINE 0x02000000 +#define BASS_INPUT_TYPE_MIC 0x03000000 +#define BASS_INPUT_TYPE_SYNTH 0x04000000 +#define BASS_INPUT_TYPE_CD 0x05000000 +#define BASS_INPUT_TYPE_PHONE 0x06000000 +#define BASS_INPUT_TYPE_SPEAKER 0x07000000 +#define BASS_INPUT_TYPE_WAVE 0x08000000 +#define BASS_INPUT_TYPE_AUX 0x09000000 +#define BASS_INPUT_TYPE_ANALOG 0x0a000000 + +// BASS_ChannelSetFX effect types +#define BASS_FX_DX8_CHORUS 0 +#define BASS_FX_DX8_COMPRESSOR 1 +#define BASS_FX_DX8_DISTORTION 2 +#define BASS_FX_DX8_ECHO 3 +#define BASS_FX_DX8_FLANGER 4 +#define BASS_FX_DX8_GARGLE 5 +#define BASS_FX_DX8_I3DL2REVERB 6 +#define BASS_FX_DX8_PARAMEQ 7 +#define BASS_FX_DX8_REVERB 8 +#define BASS_FX_VOLUME 9 + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_CHORUS; + +typedef struct { + float fGain; + float fAttack; + float fRelease; + float fThreshold; + float fRatio; + float fPredelay; +} BASS_DX8_COMPRESSOR; + +typedef struct { + float fGain; + float fEdge; + float fPostEQCenterFrequency; + float fPostEQBandwidth; + float fPreLowpassCutoff; +} BASS_DX8_DISTORTION; + +typedef struct { + float fWetDryMix; + float fFeedback; + float fLeftDelay; + float fRightDelay; + BOOL lPanDelay; +} BASS_DX8_ECHO; + +typedef struct { + float fWetDryMix; + float fDepth; + float fFeedback; + float fFrequency; + DWORD lWaveform; // 0=triangle, 1=sine + float fDelay; + DWORD lPhase; // BASS_DX8_PHASE_xxx +} BASS_DX8_FLANGER; + +typedef struct { + DWORD dwRateHz; // Rate of modulation in hz + DWORD dwWaveShape; // 0=triangle, 1=square +} BASS_DX8_GARGLE; + +typedef struct { + int lRoom; // [-10000, 0] default: -1000 mB + int lRoomHF; // [-10000, 0] default: 0 mB + float flRoomRolloffFactor; // [0.0, 10.0] default: 0.0 + float flDecayTime; // [0.1, 20.0] default: 1.49s + float flDecayHFRatio; // [0.1, 2.0] default: 0.83 + int lReflections; // [-10000, 1000] default: -2602 mB + float flReflectionsDelay; // [0.0, 0.3] default: 0.007 s + int lReverb; // [-10000, 2000] default: 200 mB + float flReverbDelay; // [0.0, 0.1] default: 0.011 s + float flDiffusion; // [0.0, 100.0] default: 100.0 % + float flDensity; // [0.0, 100.0] default: 100.0 % + float flHFReference; // [20.0, 20000.0] default: 5000.0 Hz +} BASS_DX8_I3DL2REVERB; + +typedef struct { + float fCenter; + float fBandwidth; + float fGain; +} BASS_DX8_PARAMEQ; + +typedef struct { + float fInGain; // [-96.0,0.0] default: 0.0 dB + float fReverbMix; // [-96.0,0.0] default: 0.0 db + float fReverbTime; // [0.001,3000.0] default: 1000.0 ms + float fHighFreqRTRatio; // [0.001,0.999] default: 0.001 +} BASS_DX8_REVERB; + +#define BASS_DX8_PHASE_NEG_180 0 +#define BASS_DX8_PHASE_NEG_90 1 +#define BASS_DX8_PHASE_ZERO 2 +#define BASS_DX8_PHASE_90 3 +#define BASS_DX8_PHASE_180 4 + +typedef struct { + float fTarget; + float fCurrent; + float fTime; + DWORD lCurve; +} BASS_FX_VOLUME_PARAM; + +typedef void (CALLBACK IOSNOTIFYPROC)(DWORD status); +/* iOS notification callback function. +status : The notification (BASS_IOSNOTIFY_xxx) */ + +#define BASS_IOSNOTIFY_INTERRUPT 1 // interruption started +#define BASS_IOSNOTIFY_INTERRUPT_END 2 // interruption ended + +BOOL BASSDEF(BASS_SetConfig)(DWORD option, DWORD value); +DWORD BASSDEF(BASS_GetConfig)(DWORD option); +BOOL BASSDEF(BASS_SetConfigPtr)(DWORD option, const void *value); +void *BASSDEF(BASS_GetConfigPtr)(DWORD option); +DWORD BASSDEF(BASS_GetVersion)(); +int BASSDEF(BASS_ErrorGetCode)(); +BOOL BASSDEF(BASS_GetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, HWND win, const GUID *dsguid); +#else +BOOL BASSDEF(BASS_Init)(int device, DWORD freq, DWORD flags, void *win, void *dsguid); +#endif +BOOL BASSDEF(BASS_SetDevice)(DWORD device); +DWORD BASSDEF(BASS_GetDevice)(); +BOOL BASSDEF(BASS_Free)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) +void *BASSDEF(BASS_GetDSoundObject)(DWORD object); +#endif +BOOL BASSDEF(BASS_GetInfo)(BASS_INFO *info); +BOOL BASSDEF(BASS_Update)(DWORD length); +float BASSDEF(BASS_GetCPU)(); +BOOL BASSDEF(BASS_Start)(); +BOOL BASSDEF(BASS_Stop)(); +BOOL BASSDEF(BASS_Pause)(); +BOOL BASSDEF(BASS_IsStarted)(); +BOOL BASSDEF(BASS_SetVolume)(float volume); +float BASSDEF(BASS_GetVolume)(); + +HPLUGIN BASSDEF(BASS_PluginLoad)(const char *file, DWORD flags); +BOOL BASSDEF(BASS_PluginFree)(HPLUGIN handle); +const BASS_PLUGININFO *BASSDEF(BASS_PluginGetInfo)(HPLUGIN handle); + +BOOL BASSDEF(BASS_Set3DFactors)(float distf, float rollf, float doppf); +BOOL BASSDEF(BASS_Get3DFactors)(float *distf, float *rollf, float *doppf); +BOOL BASSDEF(BASS_Set3DPosition)(const BASS_3DVECTOR *pos, const BASS_3DVECTOR *vel, const BASS_3DVECTOR *front, const BASS_3DVECTOR *top); +BOOL BASSDEF(BASS_Get3DPosition)(BASS_3DVECTOR *pos, BASS_3DVECTOR *vel, BASS_3DVECTOR *front, BASS_3DVECTOR *top); +void BASSDEF(BASS_Apply3D)(); +#if defined(_WIN32) && !defined(_WIN32_WCE) && !(WINAPI_FAMILY && WINAPI_FAMILY!=WINAPI_FAMILY_DESKTOP_APP) +BOOL BASSDEF(BASS_SetEAXParameters)(int env, float vol, float decay, float damp); +BOOL BASSDEF(BASS_GetEAXParameters)(DWORD *env, float *vol, float *decay, float *damp); +#endif + +HMUSIC BASSDEF(BASS_MusicLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD flags, DWORD freq); +BOOL BASSDEF(BASS_MusicFree)(HMUSIC handle); + +HSAMPLE BASSDEF(BASS_SampleLoad)(BOOL mem, const void *file, QWORD offset, DWORD length, DWORD max, DWORD flags); +HSAMPLE BASSDEF(BASS_SampleCreate)(DWORD length, DWORD freq, DWORD chans, DWORD max, DWORD flags); +BOOL BASSDEF(BASS_SampleFree)(HSAMPLE handle); +BOOL BASSDEF(BASS_SampleSetData)(HSAMPLE handle, const void *buffer); +BOOL BASSDEF(BASS_SampleGetData)(HSAMPLE handle, void *buffer); +BOOL BASSDEF(BASS_SampleGetInfo)(HSAMPLE handle, BASS_SAMPLE *info); +BOOL BASSDEF(BASS_SampleSetInfo)(HSAMPLE handle, const BASS_SAMPLE *info); +HCHANNEL BASSDEF(BASS_SampleGetChannel)(HSAMPLE handle, BOOL onlynew); +DWORD BASSDEF(BASS_SampleGetChannels)(HSAMPLE handle, HCHANNEL *channels); +BOOL BASSDEF(BASS_SampleStop)(HSAMPLE handle); + +HSTREAM BASSDEF(BASS_StreamCreate)(DWORD freq, DWORD chans, DWORD flags, STREAMPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags); +HSTREAM BASSDEF(BASS_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user); +HSTREAM BASSDEF(BASS_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *proc, void *user); +BOOL BASSDEF(BASS_StreamFree)(HSTREAM handle); +QWORD BASSDEF(BASS_StreamGetFilePosition)(HSTREAM handle, DWORD mode); +DWORD BASSDEF(BASS_StreamPutData)(HSTREAM handle, const void *buffer, DWORD length); +DWORD BASSDEF(BASS_StreamPutFileData)(HSTREAM handle, const void *buffer, DWORD length); + +BOOL BASSDEF(BASS_RecordGetDeviceInfo)(DWORD device, BASS_DEVICEINFO *info); +BOOL BASSDEF(BASS_RecordInit)(int device); +BOOL BASSDEF(BASS_RecordSetDevice)(DWORD device); +DWORD BASSDEF(BASS_RecordGetDevice)(); +BOOL BASSDEF(BASS_RecordFree)(); +BOOL BASSDEF(BASS_RecordGetInfo)(BASS_RECORDINFO *info); +const char *BASSDEF(BASS_RecordGetInputName)(int input); +BOOL BASSDEF(BASS_RecordSetInput)(int input, DWORD flags, float volume); +DWORD BASSDEF(BASS_RecordGetInput)(int input, float *volume); +HRECORD BASSDEF(BASS_RecordStart)(DWORD freq, DWORD chans, DWORD flags, RECORDPROC *proc, void *user); + +double BASSDEF(BASS_ChannelBytes2Seconds)(DWORD handle, QWORD pos); +QWORD BASSDEF(BASS_ChannelSeconds2Bytes)(DWORD handle, double pos); +DWORD BASSDEF(BASS_ChannelGetDevice)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetDevice)(DWORD handle, DWORD device); +DWORD BASSDEF(BASS_ChannelIsActive)(DWORD handle); +BOOL BASSDEF(BASS_ChannelGetInfo)(DWORD handle, BASS_CHANNELINFO *info); +const char *BASSDEF(BASS_ChannelGetTags)(DWORD handle, DWORD tags); +DWORD BASSDEF(BASS_ChannelFlags)(DWORD handle, DWORD flags, DWORD mask); +BOOL BASSDEF(BASS_ChannelUpdate)(DWORD handle, DWORD length); +BOOL BASSDEF(BASS_ChannelLock)(DWORD handle, BOOL lock); +BOOL BASSDEF(BASS_ChannelPlay)(DWORD handle, BOOL restart); +BOOL BASSDEF(BASS_ChannelStop)(DWORD handle); +BOOL BASSDEF(BASS_ChannelPause)(DWORD handle); +BOOL BASSDEF(BASS_ChannelSetAttribute)(DWORD handle, DWORD attrib, float value); +BOOL BASSDEF(BASS_ChannelGetAttribute)(DWORD handle, DWORD attrib, float *value); +BOOL BASSDEF(BASS_ChannelSlideAttribute)(DWORD handle, DWORD attrib, float value, DWORD time); +BOOL BASSDEF(BASS_ChannelIsSliding)(DWORD handle, DWORD attrib); +BOOL BASSDEF(BASS_ChannelSetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); +DWORD BASSDEF(BASS_ChannelGetAttributeEx)(DWORD handle, DWORD attrib, void *value, DWORD size); +BOOL BASSDEF(BASS_ChannelSet3DAttributes)(DWORD handle, int mode, float min, float max, int iangle, int oangle, float outvol); +BOOL BASSDEF(BASS_ChannelGet3DAttributes)(DWORD handle, DWORD *mode, float *min, float *max, DWORD *iangle, DWORD *oangle, float *outvol); +BOOL BASSDEF(BASS_ChannelSet3DPosition)(DWORD handle, const BASS_3DVECTOR *pos, const BASS_3DVECTOR *orient, const BASS_3DVECTOR *vel); +BOOL BASSDEF(BASS_ChannelGet3DPosition)(DWORD handle, BASS_3DVECTOR *pos, BASS_3DVECTOR *orient, BASS_3DVECTOR *vel); +QWORD BASSDEF(BASS_ChannelGetLength)(DWORD handle, DWORD mode); +BOOL BASSDEF(BASS_ChannelSetPosition)(DWORD handle, QWORD pos, DWORD mode); +QWORD BASSDEF(BASS_ChannelGetPosition)(DWORD handle, DWORD mode); +DWORD BASSDEF(BASS_ChannelGetLevel)(DWORD handle); +BOOL BASSDEF(BASS_ChannelGetLevelEx)(DWORD handle, float *levels, float length, DWORD flags); +DWORD BASSDEF(BASS_ChannelGetData)(DWORD handle, void *buffer, DWORD length); +HSYNC BASSDEF(BASS_ChannelSetSync)(DWORD handle, DWORD type, QWORD param, SYNCPROC *proc, void *user); +BOOL BASSDEF(BASS_ChannelRemoveSync)(DWORD handle, HSYNC sync); +HDSP BASSDEF(BASS_ChannelSetDSP)(DWORD handle, DSPPROC *proc, void *user, int priority); +BOOL BASSDEF(BASS_ChannelRemoveDSP)(DWORD handle, HDSP dsp); +BOOL BASSDEF(BASS_ChannelSetLink)(DWORD handle, DWORD chan); +BOOL BASSDEF(BASS_ChannelRemoveLink)(DWORD handle, DWORD chan); +HFX BASSDEF(BASS_ChannelSetFX)(DWORD handle, DWORD type, int priority); +BOOL BASSDEF(BASS_ChannelRemoveFX)(DWORD handle, HFX fx); + +BOOL BASSDEF(BASS_FXSetParameters)(HFX handle, const void *params); +BOOL BASSDEF(BASS_FXGetParameters)(HFX handle, void *params); +BOOL BASSDEF(BASS_FXReset)(HFX handle); +BOOL BASSDEF(BASS_FXSetPriority)(HFX handle, int priority); + +#ifdef __cplusplus +} + +#if defined(_WIN32) && !defined(NOBASSOVERLOADS) +static inline HPLUGIN BASS_PluginLoad(const WCHAR *file, DWORD flags) +{ + return BASS_PluginLoad((const char*)file, flags|BASS_UNICODE); +} + +static inline HMUSIC BASS_MusicLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD flags, DWORD freq) +{ + return BASS_MusicLoad(mem, (const void*)file, offset, length, flags|BASS_UNICODE, freq); +} + +static inline HSAMPLE BASS_SampleLoad(BOOL mem, const WCHAR *file, QWORD offset, DWORD length, DWORD max, DWORD flags) +{ + return BASS_SampleLoad(mem, (const void*)file, offset, length, max, flags|BASS_UNICODE); +} + +static inline HSTREAM BASS_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags) +{ + return BASS_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE); +} + +static inline HSTREAM BASS_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user) +{ + return BASS_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user); +} + +static inline BOOL BASS_SetConfigPtr(DWORD option, const WCHAR *value) +{ + return BASS_SetConfigPtr(option|BASS_UNICODE, (const void*)value); +} +#endif +#endif + +#endif diff --git a/hsmodem/basswasapi.h b/hsmodem/basswasapi.h new file mode 100755 index 0000000..6497793 --- /dev/null +++ b/hsmodem/basswasapi.h @@ -0,0 +1,161 @@ +/* + BASSWASAPI 2.4 C/C++ header file + Copyright (c) 2009-2020 Un4seen Developments Ltd. + + See the BASSWASAPI.CHM file for more detailed documentation +*/ + +#ifndef BASSWASAPI_H +#define BASSWASAPI_H + +#include "bass.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef BASSWASAPIDEF +#define BASSWASAPIDEF(f) WINAPI f +#endif + +// Additional error codes returned by BASS_ErrorGetCode +#define BASS_ERROR_WASAPI 5000 // no WASAPI +#define BASS_ERROR_WASAPI_BUFFER 5001 // buffer size is invalid +#define BASS_ERROR_WASAPI_CATEGORY 5002 // can't set category +#define BASS_ERROR_WASAPI_DENIED 5003 // access denied + +// Device info structure +typedef struct { + const char *name; + const char *id; + DWORD type; + DWORD flags; + float minperiod; + float defperiod; + DWORD mixfreq; + DWORD mixchans; +} BASS_WASAPI_DEVICEINFO; + +typedef struct { + DWORD initflags; + DWORD freq; + DWORD chans; + DWORD format; + DWORD buflen; + float volmax; + float volmin; + float volstep; +} BASS_WASAPI_INFO; + +// BASS_WASAPI_DEVICEINFO "type" +#define BASS_WASAPI_TYPE_NETWORKDEVICE 0 +#define BASS_WASAPI_TYPE_SPEAKERS 1 +#define BASS_WASAPI_TYPE_LINELEVEL 2 +#define BASS_WASAPI_TYPE_HEADPHONES 3 +#define BASS_WASAPI_TYPE_MICROPHONE 4 +#define BASS_WASAPI_TYPE_HEADSET 5 +#define BASS_WASAPI_TYPE_HANDSET 6 +#define BASS_WASAPI_TYPE_DIGITAL 7 +#define BASS_WASAPI_TYPE_SPDIF 8 +#define BASS_WASAPI_TYPE_HDMI 9 +#define BASS_WASAPI_TYPE_UNKNOWN 10 + +// BASS_WASAPI_DEVICEINFO flags +#define BASS_DEVICE_ENABLED 1 +#define BASS_DEVICE_DEFAULT 2 +#define BASS_DEVICE_INIT 4 +#define BASS_DEVICE_LOOPBACK 8 +#define BASS_DEVICE_INPUT 16 +#define BASS_DEVICE_UNPLUGGED 32 +#define BASS_DEVICE_DISABLED 64 + +// BASS_WASAPI_Init flags +#define BASS_WASAPI_EXCLUSIVE 1 +#define BASS_WASAPI_AUTOFORMAT 2 +#define BASS_WASAPI_BUFFER 4 +#define BASS_WASAPI_EVENT 16 +#define BASS_WASAPI_SAMPLES 32 +#define BASS_WASAPI_DITHER 64 +#define BASS_WASAPI_RAW 128 +#define BASS_WASAPI_ASYNC 0x100 + +#define BASS_WASAPI_CATEGORY_MASK 0xf000 +#define BASS_WASAPI_CATEGORY_OTHER 0x0000 +#define BASS_WASAPI_CATEGORY_FOREGROUNDONLYMEDIA 0x1000 +#define BASS_WASAPI_CATEGORY_BACKGROUNDCAPABLEMEDIA 0x2000 +#define BASS_WASAPI_CATEGORY_COMMUNICATIONS 0x3000 +#define BASS_WASAPI_CATEGORY_ALERTS 0x4000 +#define BASS_WASAPI_CATEGORY_SOUNDEFFECTS 0x5000 +#define BASS_WASAPI_CATEGORY_GAMEEFFECTS 0x6000 +#define BASS_WASAPI_CATEGORY_GAMEMEDIA 0x7000 +#define BASS_WASAPI_CATEGORY_GAMECHAT 0x8000 +#define BASS_WASAPI_CATEGORY_SPEECH 0x9000 +#define BASS_WASAPI_CATEGORY_MOVIE 0xa000 +#define BASS_WASAPI_CATEGORY_MEDIA 0xb000 + +// BASS_WASAPI_INFO "format" +#define BASS_WASAPI_FORMAT_FLOAT 0 +#define BASS_WASAPI_FORMAT_8BIT 1 +#define BASS_WASAPI_FORMAT_16BIT 2 +#define BASS_WASAPI_FORMAT_24BIT 3 +#define BASS_WASAPI_FORMAT_32BIT 4 + +// BASS_WASAPI_Set/GetVolume modes +#define BASS_WASAPI_CURVE_DB 0 +#define BASS_WASAPI_CURVE_LINEAR 1 +#define BASS_WASAPI_CURVE_WINDOWS 2 +#define BASS_WASAPI_VOL_SESSION 8 + +typedef DWORD (CALLBACK WASAPIPROC)(void *buffer, DWORD length, void *user); +/* WASAPI callback function. +buffer : Buffer containing the sample data +length : Number of bytes +user : The 'user' parameter given when calling BASS_WASAPI_Init +RETURN : The number of bytes written (output devices), 0/1 = stop/continue (input devices) */ + +// Special WASAPIPROCs +#define WASAPIPROC_PUSH (WASAPIPROC*)0 // push output +#define WASAPIPROC_BASS (WASAPIPROC*)-1 // BASS channel + +typedef void (CALLBACK WASAPINOTIFYPROC)(DWORD notify, DWORD device, void *user); +/* WASAPI device notification callback function. +notify : The notification (BASS_WASAPI_NOTIFY_xxx) +device : Device that the notification applies to +user : The 'user' parameter given when calling BASS_WASAPI_SetNotify */ + +// Device notifications +#define BASS_WASAPI_NOTIFY_ENABLED 0 +#define BASS_WASAPI_NOTIFY_DISABLED 1 +#define BASS_WASAPI_NOTIFY_DEFOUTPUT 2 +#define BASS_WASAPI_NOTIFY_DEFINPUT 3 +#define BASS_WASAPI_NOTIFY_FAIL 0x100 + +DWORD BASSWASAPIDEF(BASS_WASAPI_GetVersion)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_SetNotify)(WASAPINOTIFYPROC *proc, void *user); +BOOL BASSWASAPIDEF(BASS_WASAPI_GetDeviceInfo)(DWORD device, BASS_WASAPI_DEVICEINFO *info); +float BASSWASAPIDEF(BASS_WASAPI_GetDeviceLevel)(DWORD device, int chan); +BOOL BASSWASAPIDEF(BASS_WASAPI_SetDevice)(DWORD device); +DWORD BASSWASAPIDEF(BASS_WASAPI_GetDevice)(); +DWORD BASSWASAPIDEF(BASS_WASAPI_CheckFormat)(DWORD device, DWORD freq, DWORD chans, DWORD flags); +BOOL BASSWASAPIDEF(BASS_WASAPI_Init)(int device, DWORD freq, DWORD chans, DWORD flags, float buffer, float period, WASAPIPROC *proc, void *user); +BOOL BASSWASAPIDEF(BASS_WASAPI_Free)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_GetInfo)(BASS_WASAPI_INFO *info); +float BASSWASAPIDEF(BASS_WASAPI_GetCPU)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_Lock)(BOOL lock); +BOOL BASSWASAPIDEF(BASS_WASAPI_Start)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_Stop)(BOOL reset); +BOOL BASSWASAPIDEF(BASS_WASAPI_IsStarted)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_SetVolume)(DWORD mode, float volume); +float BASSWASAPIDEF(BASS_WASAPI_GetVolume)(DWORD mode); +BOOL BASSWASAPIDEF(BASS_WASAPI_SetMute)(DWORD mode, BOOL mute); +BOOL BASSWASAPIDEF(BASS_WASAPI_GetMute)(DWORD mode); +DWORD BASSWASAPIDEF(BASS_WASAPI_PutData)(void *buffer, DWORD length); +DWORD BASSWASAPIDEF(BASS_WASAPI_GetData)(void *buffer, DWORD length); +DWORD BASSWASAPIDEF(BASS_WASAPI_GetLevel)(); +BOOL BASSWASAPIDEF(BASS_WASAPI_GetLevelEx)(float *levels, float length, DWORD flags); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/hsmodem/basswasapi.lib b/hsmodem/basswasapi.lib new file mode 100644 index 0000000000000000000000000000000000000000..c7155e3cdf3d828f937db0a162e8c4300c1a399e GIT binary patch literal 7164 zcmcIo%}*Og6n{1W5{K|%V?I^ns6@LI-I?**wOxmmp4T()z4^_@oAPu@&^tM?~GGnGlt^S_%B07wD!Jp$-|4KVNyVB~;P>^T6Vp+!!^ zQ2<60)11b$0E}W&oJKbR7!AGQH2e(Zk)ml%V?_W)lf#0Z;u~r7jMLaD@{uM^IE}o; zc_59y;uL=mz$p5XQ@jV;j2<&8mkZ0Q_tw_S`P-$XwZiK9y|wbO0Oj(^ zMzPo^15Z35F0%f^#>(Ateqnt9oB_&wg!1>6ec!4dRci;iBo0^IKP(6E*{F(U-g;QA zScQX~T5jG)Sr<|Dmv*hngFChQ{+69fWhr%2Le<83^P!8@Lu;=Iyep%QP_pcmnqA%b zjaJs!h8{=G%~6v^J&&#Gxij|NXrYJapz0M4s&;NRO<}n#RsK%hvSB5mSh_y{4Xlzw) z_1MmD*;}-=C`?rcjp2T6?|9#$wKTS>hr1~B{LaN=t9m%#^0DoYCYh=ZVmaM@NRnyj z`0oV{D4B*1zlVN)#^q94w|~v0$UA^&jv^OmKW5CjF=GM%9`ymd?gw}`0B|q@@H_^v zIE0=Vz56r@WXA!fuy1n|;0^Xa!~QfzkK!0cg-L*?NN319#r6rxzr`_Lq0aj_z)O_t z!S`b%3{KDkeb5hM5P@#!g)1-)6EF%FAP$!y3Ih;>OE3Z#VHgHs2tp8UQ=?1wBSGHO z$1@N&+5d29@5SV`C}A8fXOa#YRi$e(lv=SAL&e96mDpz}&=-vKxV|ofa&G>fLTn)3 zLv->Ld29YqBX4aTeNMmc{;E4wX7U@+;MbG>K*e#?g zt|^kkNP{Gqu37qXgWQ-jQBqqmRGQDj4C%yOqixjGOt+CO4Y-k`m~kT$ZPqhplI^UO z%o$PFGi*}VGjD<|jhtdRrv8MPzes+apCKjL9y0o)QT_6oyK_JQ*hg;dz1Y& z7l_(Lpo(|^()Z{puK6N?Dw9 0 && pdata[0] == 0x3c) { - setAudioDevices(pdata[1], pdata[2]); + setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4]); char rxip[20]; strcpy(rxip, inet_ntoa(rxsock->sin_addr)); @@ -311,12 +318,6 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) uint8_t type = pdata[0]; uint8_t minfo = pdata[1]; - if (len != (PAYLOADLEN + 2)) - { - printf("data from app: wrong length:%d (should be %d)\n", len - 2, PAYLOADLEN); - return; - } - // type values: see oscardata config.cs: frame types if (type == 16) { @@ -362,8 +363,30 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) { // reset liquid RX modem resetModem(); + return; } + if (type == 21) + { + // set playback volume (in % 0..100) + setVolume(0,minfo); + return; + } + + if (type == 22) + { + // set capture volume (in % 0..100) + setVolume(1,minfo); + return; + } + + if (len != (PAYLOADLEN + 2)) + { + printf("data from app: wrong length:%d (should be %d)\n", len - 2, PAYLOADLEN); + return; + } + + //if (getSending() == 1) return; // already sending (Array sending) if (minfo == 0) @@ -376,7 +399,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // and bits: symbols * bitsPerSymbol // and bytes/second: bits/8 = (caprate/txinterpolfactor) * bitsPerSymbol / 8 // one frame has 258 bytes, so we need for 5s: 5* ((caprate/txinterpolfactor) * bitsPerSymbol / 8) /258 + 1 frames - int numframespreamble = 3 * ((caprate / txinterpolfactor) * bitsPerSymbol / 8) / 258 + 1; + int numframespreamble = 5 * ((caprate / txinterpolfactor) * bitsPerSymbol / 8) / 258 + 1; for (int i = 0; i < numframespreamble; i++) toGR_sendData(pdata + 2, type, minfo); } @@ -427,7 +450,7 @@ void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock) // no frame found // if longer ws seconds nothing found, reset liquid RX modem // comes here with symbol rate, i.e. 4000 S/s - int ws = 2; + int ws = 4; int wt = sr[speedmode].audio / sr[speedmode].tx; if (++fnd >= (wt * ws)) { diff --git a/hsmodem/hsmodem.h b/hsmodem/hsmodem.h index fdc2a95..b677a6f 100755 --- a/hsmodem/hsmodem.h +++ b/hsmodem/hsmodem.h @@ -33,6 +33,7 @@ #include #pragma comment(lib, "bass.lib") +#pragma comment(lib, "basswasapi.lib") #pragma comment(lib, "libliquid.lib") #pragma comment(lib, "fftw_lib/libfftw3-3.lib") #endif @@ -53,6 +54,7 @@ #endif #include "bass.h" +#include "basswasapi.h" #include "liquid.h" #include "frameformat.h" #include "fec.h" @@ -64,6 +66,10 @@ #define CRC16RX 1 #define CRC16FILE 2 +// definitions for audio +#define MAXDEVSTRLEN 2000 +#define CHANNELS 1 // no of channels used + void init_packer(); uint8_t* Pack(uint8_t* payload, int type, int status, int* plen); uint8_t* unpack_data(uint8_t* rxd, int len); @@ -88,7 +94,8 @@ uint8_t* RX_Scramble(uint8_t* data, int len); uint16_t Crc16_messagecalc(int rxtx, uint8_t* data, int len); void showbytestring(char* title, uint8_t* data, int anz); -void measure_speed(int len); +void measure_speed_syms(int len); +void measure_speed_bps(int len); void initFEC(); void GetFEC(uint8_t* txblock, int len, uint8_t* destArray); @@ -100,11 +107,16 @@ void pb_write_fifo_clear(); void pb_write_fifo(float sample); int cap_read_fifo(float* data); uint8_t* getAudioDevicelist(int* len); +void setPBvolume(int v); +void setCAPvolume(int v); +void setVolume(int pbcap, int v); +int init_wasapi(int pbdev, int capdev); void sleep_ms(int ms); void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock); void modulator(uint8_t sym_in); +int pb_fifo_usedBlocks(); void init_dsp(); int demodulator(); void sendToModulator(uint8_t* d, int len); @@ -127,7 +139,7 @@ extern int UdpDataPort_ModemToApp; extern int txinterpolfactor; extern int rxPreInterpolfactor; extern char appIP[20]; - +extern float softwareCAPvolume; #ifdef _LINUX_ int isRunning(char* prgname); diff --git a/hsmodem/hsmodem.vcxproj b/hsmodem/hsmodem.vcxproj index 1eb77cb..c9ffd29 100755 --- a/hsmodem/hsmodem.vcxproj +++ b/hsmodem/hsmodem.vcxproj @@ -220,6 +220,8 @@ + + @@ -229,6 +231,7 @@ + diff --git a/hsmodem/hsmodem.vcxproj.filters b/hsmodem/hsmodem.vcxproj.filters index 0f4731c..2de982a 100755 --- a/hsmodem/hsmodem.vcxproj.filters +++ b/hsmodem/hsmodem.vcxproj.filters @@ -51,6 +51,9 @@ Source Files + + Source Files + @@ -74,5 +77,11 @@ Header Files + + Header Files + + + Header Files + \ No newline at end of file diff --git a/hsmodem/liquid_if.cpp b/hsmodem/liquid_if.cpp index 95870ce..3f694f5 100755 --- a/hsmodem/liquid_if.cpp +++ b/hsmodem/liquid_if.cpp @@ -288,6 +288,9 @@ void make_FFTdata(float f) int bidx = 0; txpl[bidx++] = 4; // type 4: FFT data follows + int us = pb_fifo_usedBlocks(); + if (us > 255) us = 255; + txpl[bidx++] = us; // usage of TX fifo for (int i = 0; i < fftlen; i++) { @@ -311,6 +314,11 @@ static int ccol_idx = 0; int ret = cap_read_fifo(&f); if(ret == 0) return 0; + // input volume +#ifdef _WIN32_ + f *= softwareCAPvolume; +#endif + make_FFTdata(f*120); // downconvert into baseband @@ -345,7 +353,7 @@ static int ccol_idx = 0; unsigned int sym_out; // output symbol modem_demodulate(demod, syms, &sym_out); - measure_speed(1); + //measure_speed_syms(1); // try to extract a complete frame uint8_t symb = sym_out; @@ -356,7 +364,7 @@ static int ccol_idx = 0; // we have about 2000 S/s, but this many points would make the GUI slow // so we send only every x static int ev = 0; - //if (++ev >= 2) + if (++ev >= 2) { ev = 0; uint32_t re = (uint32_t)(syms.real * 16777216.0); diff --git a/hsmodem/speed.cpp b/hsmodem/speed.cpp index 3806206..114ad61 100755 --- a/hsmodem/speed.cpp +++ b/hsmodem/speed.cpp @@ -28,6 +28,7 @@ int speed = 0; #define MAXSPDARR 5 int spdarr[MAXSPDARR]; +int spdarrbps[MAXSPDARR]; #ifdef _LINUX_ int getus() @@ -79,9 +80,37 @@ static int f=1; return ssum; } +int meanvalbps(int v) +{ + static int f = 1; + + if (f) + { + for (int i = 0; i < MAXSPDARR; i++) spdarrbps[i] = -1; + f = 0; + } + + for (int i = (MAXSPDARR - 1); i > 0; i--) + spdarrbps[i] = spdarrbps[i - 1]; + spdarrbps[0] = v; + + int ssum = 0; + int cnt = 0; + for (int i = 0; i < MAXSPDARR; i++) + { + if (spdarrbps[i] != -1) + { + ssum += spdarrbps[i]; + cnt++; + } + } + ssum /= cnt; + return ssum; +} + // len ... number of symbols // measures and calculates the speed in bit / s -void measure_speed(int len) +void measure_speed_syms(int len) { static int lasttim = 0; static int elems = 0; @@ -96,15 +125,43 @@ void measure_speed(int len) elems += len; - if(timespan < 2000000) return; + if(timespan < 1000000) return; double dspd = elems; dspd = dspd * 1e6 / timespan; speed = meanval((int)dspd) * bitsPerSymbol; // here we have number of elements after 1s - //printf("%d items/s\n",speed); + printf("%d sym/s\n",speed); elems=0; lasttim = tim; } + +void measure_speed_bps(int len) +{ + static int lasttim = 0; + static int elems = 0; + + int tim = getus(); + int timespan = tim - lasttim; + if (timespan < 0) + { + lasttim = tim; + return; + } + + + elems += len; + if (timespan < 1000000) return; + + double dspd = elems; + dspd = dspd * 1e6 / timespan; + speed = meanvalbps((int)dspd); + + // here we have number of elements after 1s + printf("%d bit/s\n", speed); + + elems = 0; + lasttim = tim; +} diff --git a/hsmodem/udp.cpp b/hsmodem/udp.cpp index 19f2d16..31c0143 100755 --- a/hsmodem/udp.cpp +++ b/hsmodem/udp.cpp @@ -106,6 +106,7 @@ void UdpRxInit(int *sock, int port, void (*rxfunc)(uint8_t *, int, struct sockad #ifdef _LINUX_ void* threadfunction(void* param) { socklen_t fromlen; + pthread_detach(pthread_self()); #endif #ifdef _WIN32_ @@ -129,6 +130,7 @@ void threadfunction(void* param) { } #ifdef _LINUX_ + pthread_exit(NULL); // self terminate this thread return NULL; #endif } diff --git a/oscardata/.vs/oscardata/v16/.suo b/oscardata/.vs/oscardata/v16/.suo index 41a9b176c9ff806025344acdd2766bdd9b073f29..a3129304419e92de7e24d85b791e2e8ba3708a27 100755 GIT binary patch delta 9439 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 3) return; - - Byte[] txdata = new byte[statics.PayloadLen + 2]; - - txdata[0] = (Byte)statics.BERtest; // BER Test Marker - txdata[1] = frameinfo; - - Byte tb = (Byte)'A'; - for (int i = 2; i < txdata.Length; i++) + if (Udp.GetBufferCount() < 2) { - txdata[i] = tb; - tb++; - if (tb == 'z') tb = (Byte)'A'; + Byte[] txdata = new byte[statics.PayloadLen + 2]; + + txdata[0] = (Byte)statics.BERtest; // BER Test Marker + txdata[1] = frameinfo; + + Byte tb = (Byte)'A'; + for (int i = 2; i < txdata.Length; i++) + { + txdata[i] = tb; + tb++; + if (tb == 'z') tb = (Byte)'A'; + } + + // and transmit it + Udp.UdpSendData(txdata); + + frameinfo = (Byte)statics.NextFrame; } - - // and transmit it - Udp.UdpSend(txdata); - - frameinfo = (Byte)statics.NextFrame; - txframecounter++; } if (ArraySend.getSending()) @@ -169,10 +172,14 @@ namespace oscardata if (ts_ip.Text.Contains("?") || ts_ip.Text.Contains("1.2.3.4") || old_tsip != statics.ModemIP) { if (statics.ModemIP == "1.2.3.4") + { ts_ip.Text = "Modem-IP: ?"; + ts_ip.ForeColor = Color.Red; + } else { ts_ip.Text = "Modem-IP: " + statics.ModemIP; + ts_ip.ForeColor = Color.Black; old_tsip = statics.ModemIP; comboBox1_SelectedIndexChanged(null, null); // send speed to modem } @@ -193,11 +200,38 @@ namespace oscardata cb_audioCAP.Items.Add(s); } } + + + if (setPBvolume >= 0) + { + Byte[] txdata = new byte[2]; + txdata[0] = (Byte)statics.SetPBvolume; + txdata[1] = (Byte)setPBvolume; + Udp.UdpSendCtrl(txdata); + setPBvolume = -1; + } + + if (setCAPvolume != -1) + { + Byte[] txdata = new byte[2]; + txdata[0] = (Byte)statics.SetCAPvolume; + txdata[1] = (Byte)setCAPvolume; + Udp.UdpSendCtrl(txdata); + setCAPvolume = -1; + } + + /*if(modemrunning == false) + { + // start hsmodem (.exe) + modemrunning = statics.StartHSmodem(); + }*/ } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { save_Setup(); + statics.killall("hsmodem"); + statics.killall("hsmodem.exe"); // exit the threads statics.running = false; Udp.Close(); @@ -633,6 +667,8 @@ namespace oscardata panel_constel.Invalidate(); panel_txspectrum.Invalidate(); + + progressBar_fifo.Value = statics.PBfifousage; } private void panel_constel_Paint(object sender, PaintEventArgs e) @@ -934,7 +970,6 @@ namespace oscardata private void button_startBERtest_Click(object sender, EventArgs e) { - txframecounter = 1; ber = 0; framelost = 0; totallostframes = 0; @@ -978,8 +1013,7 @@ namespace oscardata private void BERcheck(Byte[] rxdata) { - String line = "RX: " + rxframecounter.ToString().PadLeft(6, ' ') + - " TX: " + txframecounter.ToString().PadLeft(6, ' ') + " "; + String line = "RX: " + rxframecounter.ToString().PadLeft(6, ' ') + " "; // print payload (must be printable chars) line += Encoding.UTF8.GetString(rxdata).Substring(0, 50) + " ..."; @@ -1100,6 +1134,9 @@ namespace oscardata label_speed.Location = new Point(panel_txspectrum.Location.X + panel_txspectrum.Size.Width + 20,panel_txspectrum.Location.Y+10); cb_speed.Location = new Point(label_speed.Location.X + label_speed.Size.Width + 10, label_speed.Location.Y-5); + + label_fifo.Location = new Point(label_speed.Location.X, label_speed.Location.Y + 35); + progressBar_fifo.Location = new Point(cb_speed.Location.X, cb_speed.Location.Y + 35); } public String GetMyBroadcastIP() @@ -1148,10 +1185,12 @@ namespace oscardata private void search_modem() { - Byte[] txb = new byte[3]; + Byte[] txb = new byte[5]; txb[0] = 0x3c; // ID of this message txb[1] = getPBaudioDevice(); txb[2] = getCAPaudioDevice(); + txb[3] = (Byte)tb_PBvol.Value; + txb[4] = (Byte)tb_CAPvol.Value; Udp.UdpBCsend(txb, GetMyBroadcastIP(), statics.UdpBCport_AppToModem); @@ -1254,7 +1293,7 @@ namespace oscardata txdata[1] = (Byte)idx; // and send info to modem - Udp.UdpSend(txdata); + Udp.UdpSendCtrl(txdata); //txcommand = statics.noTX; // stop any ongoing transmission @@ -1363,6 +1402,8 @@ namespace oscardata cb_savegoodfiles.Checked = (s == "1"); cb_audioPB.Text = ReadString(sr); cb_audioCAP.Text = ReadString(sr); + tb_PBvol.Value = ReadInt(sr); + tb_CAPvol.Value = ReadInt(sr); } } catch @@ -1387,6 +1428,8 @@ namespace oscardata sw.WriteLine(cb_savegoodfiles.Checked ? "1" : "0"); sw.WriteLine(cb_audioPB.Text); sw.WriteLine(cb_audioCAP.Text); + sw.WriteLine(tb_PBvol.Value.ToString()); + sw.WriteLine(tb_CAPvol.Value.ToString()); } } catch { } @@ -1397,11 +1440,9 @@ namespace oscardata DialogResult dr = MessageBox.Show("Do you want to shut down the Modem-Computer ?", "Shut Down Modem", MessageBoxButtons.YesNo); if (dr == DialogResult.Yes) { - Byte[] txdata = new byte[statics.PayloadLen + 2]; + Byte[] txdata = new byte[1]; txdata[0] = (Byte)statics.Modem_shutdown; - - // and transmit it - Udp.UdpSend(txdata); + Udp.UdpSendCtrl(txdata); MessageBox.Show("Please wait abt. 1 minute before powering OFF the modem", "Shut Down Modem", MessageBoxButtons.OK); } @@ -1411,20 +1452,33 @@ namespace oscardata // TEST ONLY: tell modem to send a file private void button1_Click(object sender, EventArgs e) { - Byte[] txdata = new byte[statics.PayloadLen + 2]; + Byte[] txdata = new byte[1]; txdata[0] = (Byte)statics.AutosendFile; // and transmit it - Udp.UdpSend(txdata); + Udp.UdpSendCtrl(txdata); } private void bt_resetmodem_Click(object sender, EventArgs e) { - Byte[] txdata = new byte[statics.PayloadLen + 2]; + Byte[] txdata = new byte[1]; txdata[0] = (Byte)statics.ResetModem; // and transmit it - Udp.UdpSend(txdata); + Udp.UdpSendCtrl(txdata); + } + + int setPBvolume = -1; + int setCAPvolume = -1; + + private void tb_PBvol_Scroll(object sender, EventArgs e) + { + setPBvolume = tb_PBvol.Value; + } + + private void tb_CAPvol_Scroll(object sender, EventArgs e) + { + setCAPvolume = tb_CAPvol.Value; } } } diff --git a/oscardata/oscardata/bin/Release/oscardata.exe b/oscardata/oscardata/bin/Release/oscardata.exe index 23299c3a2837d1cb3543985be978cbdef633b696..909973a21b79f0c9d6280906821969a3ba92ec66 100755 GIT binary patch delta 36726 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 delta 33142 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 z zZ`GS{5dYlfY!+Tg!afp)T9y(@ux}S|AN&r4)`eDrghQy~K~FnEz(Q-FF8A>(HT&*D zP=eXt7^Vi@8oUZnb3{G0!yRxNXeEl-+jU;k70SNv4Rz+m?`k%GPj2`9KG(Uc+TMh@ zDiEl1K}*10X?n>q`eTc`q>|U=1^&R`>o6EVmT0CDz<)|4l>L2xy34H##Vr{h1<-Y& z>|eY>gOxxa*!K-HKBLfXa0NGbNFOlxW-FmHB^9KIZit&Gst@(u=|<)3Z{Ub5t>@B4 zCi-rtOK`(zKjI$n2RDojZkR~Ql=?bZGDTjd%gao8IYeHNhpOWDGtsBmk~trFP!}LP zv|)j~w0nduJ%9^{`%1r$65$`A?3bbJlLifl4JYbGXhWw-#Tz=kUi4>xi~mu9x=z!B z8Rq&Dgcl(f5ef4O_AyAOip#w>T z_#z!VCe1uZUlWekA-qbR$pfhl|Dgv=OZYFe*1HVT)>Ydk$J`2VeJ2Mf(oXjCxn@%Gbh^$s;2a(~Mvjt}F3x4gRfj8&!A?qvF`X z!1quqz@o79qR+E^1kTO9_S)3pebr!&Ao@jszBqwK0#gV~N8vuX6J8%-Q~2HJ2MiP% zqXNU#1s>kQPAaAgu{IGsYC&Bn`=E1u*ttH-y=a2M_@h|{!N^`27((+-_DbYW_BZ%{ z0Fj0w%E6CtL3({8=c9nvNLEAgOZ=x1GofK=6KPV3D1-)NclB54n$I4QCqFtNQz z6Nw9e*qRs9A|@L&iQ#lC3h0dKXh>)umz((nrxTuiamN*JoUiPtd-I`V#vB*hzL+)- zh@rrJr#NFO9+?3-=GfWCZohK$vMb(SHs|K8PtU!1`p@p$sW&TbCG-$paLWI^L3px% zXhePHfUEZ#qa1y8V4U(hW#-PmjZ=13D)X { }; // schreibe Output ins nichts + proc.StartInfo.RedirectStandardError = true; + proc.ErrorDataReceived += (sender, args) => { }; // schreibe Output ins nichts + proc.StartInfo.Arguments = s; + proc.Start(); + proc.WaitForExit(); + } + catch { } + } + } } } diff --git a/oscardata/oscardata/oscardata.csproj b/oscardata/oscardata/oscardata.csproj index 9765068..bed1928 100755 --- a/oscardata/oscardata/oscardata.csproj +++ b/oscardata/oscardata/oscardata.csproj @@ -82,7 +82,6 @@ Resources.resx True - SettingsSingleFileGenerator Settings.Designer.cs diff --git a/oscardata/oscardata/udp.cs b/oscardata/oscardata/udp.cs index dffafca..aa85331 100755 --- a/oscardata/oscardata/udp.cs +++ b/oscardata/oscardata/udp.cs @@ -16,7 +16,6 @@ using System.Drawing; using System.Net; using System.Net.Sockets; using System.Threading; -using System.Windows.Forms.VisualStyles; namespace oscardata { @@ -29,6 +28,7 @@ namespace oscardata // Pipes for data transferred via UDP ports static UdpQueue uq_rx = new UdpQueue(); static UdpQueue uq_tx = new UdpQueue(); + static UdpQueue uq_ctrl = new UdpQueue(); static UdpQueue uq_fft = new UdpQueue(); static UdpQueue uq_iq = new UdpQueue(); @@ -83,13 +83,13 @@ namespace oscardata int rxtype = rxarr[0]; Byte[] b = new byte[rxarr.Length - 1]; Array.Copy(rxarr, 1, b, 0, b.Length); - + // payload - if (rxtype == 1) + if (rxtype == statics.udp_payload) uq_rx.Add(b); // Broadcast response - if (rxtype == 3) + if (rxtype == statics.udp_bc) { statics.ModemIP = RemoteEndpoint.Address.ToString(); searchtimeout = 0; @@ -103,11 +103,16 @@ namespace oscardata } // FFT data - if (rxtype == 4) - uq_fft.Add(b); + if (rxtype == statics.udp_fft) + { + statics.PBfifousage = b[0]; + Byte[] b1 = new byte[b.Length - 1]; + Array.Copy(b, 1, b1, 0, b1.Length); + uq_fft.Add(b1); + } // IQ data - if (rxtype == 5) + if (rxtype == statics.udp_iq) { for (int i = 0; i < b.Length; i++) { @@ -167,7 +172,7 @@ namespace oscardata } static int panelw = 75, panelh = 75; - static int maxdrawanz = 250; + static int maxdrawanz = 160; static int drawanz = 0; static Bitmap bm; static void drawBitmap(int re, int im) @@ -194,7 +199,7 @@ namespace oscardata int x = panelw / 2 + (int)fre; int y = panelh / 2 + (int)fim; - int et = 1; + int et = 2; gr.FillEllipse(Brushes.Blue, x - et, y - et, et * 2, et * 2); } } @@ -209,35 +214,62 @@ namespace oscardata // calculate cycle time for the requested data rate // time in ms for one bit: 1000/statics.datarate - int actdatarate = statics.getDatarate(); - int wait_datarate = (int)(((double)statics.UdpBlocklen * 8.0 * 1000.0 / (double)(statics.getDatarate()))); + //int actdatarate = statics.getDatarate(); + //int wait_datarate = (int)(((double)statics.UdpBlocklen * 8.0 * 1000.0 / (double)(statics.getDatarate()))); + //Timer TTimer = new Timer(new TimerCallback(TXTickTimer), autoEvent, 0, wait_datarate); - Timer TTimer = new Timer(new TimerCallback(TXTickTimer), autoEvent, 0, wait_datarate); + while (statics.running) + { + bool wait = true; + if(uq_ctrl.Count() > 0) + { + // Control Message: send immediately + Byte[] b = uq_ctrl.Getarr(); + udpc.Send(b, b.Length, statics.ModemIP, statics.UdpTXport); + wait = false; + } + if(statics.PBfifousage < 2) + { + // we need to send more payload data + if (uq_tx.Count() > 0) + { + Byte[] b = uq_tx.Getarr(); + udpc.Send(b, b.Length, statics.ModemIP, statics.UdpTXport); + wait = false; + } + } + if (wait) Thread.Sleep(1); + } + + /* while (statics.running) { autoEvent.WaitOne(); try { - if (uq_tx.Count() > 0) + while (uq_tx.Count() > 0) { // TX data available Byte[] b = uq_tx.Getarr(); udpc.Send(b, b.Length, statics.ModemIP, statics.UdpTXport); + if (b[0] < 16) break; // continue without pause for internal control messages, or break for TX messages } } catch (Exception e) { String err = e.ToString(); } - if(statics.getDatarate() != actdatarate) + + // do not wait in case of internal messages + if (statics.getDatarate() != actdatarate) { // rate has been changed, reset the timer wait_datarate = (int)(((double)statics.UdpBlocklen * 8.0 * 1000.0 / (double)(statics.getDatarate()))); TTimer.Change(0, wait_datarate); - actdatarate = statics.getDatarate(); + actdatarate = statics.getDatarate(); } - } + }*/ } public static void UdpBCsend(Byte[] b, String ip, int port) @@ -257,16 +289,26 @@ namespace oscardata // send a Byte array via UDP // this function can be called from anywhere in the program // it transfers the data to the udp-tx thread via a thread-safe pipe - public static void UdpSend(Byte[] b) + public static void UdpSendData(Byte[] b) { uq_tx.Add(b); } + public static void UdpSendCtrl(Byte[] b) + { + uq_ctrl.Add(b); + } + public static int GetBufferCount() { return uq_tx.Count(); } + public static int GetBufferCountCtrl() + { + return uq_ctrl.Count(); + } + public static Byte[] UdpReceive() { if (uq_rx.Count() == 0) return null;