update
This commit is contained in:
parent
cedbae4628
commit
6adaf44425
|
@ -25,9 +25,9 @@ Raspberry 4 (3B+)
|
|||
this software uses these programs:
|
||||
* Shifra Reed Solomon code: https://www.schifra.com/ (GPL V.2)
|
||||
* liquid-SDR: https://github.com/jgaeddert/liquid-dsp (MIT License)
|
||||
* BASS Audio: https://www.un4seen.com/ (free for non-commercial use)
|
||||
* libsoundio: https://github.com/andrewrk/libsoundio (MIT License)
|
||||
* fftw3: http://www.fftw.org (GPL V.2 or later)
|
||||
* libcodec2 (Linux: standard lib, Windows: from freeDV)
|
||||
* libcodec2: https://github.com/drowe67/codec2 (LGPL 2.1, Linux: standard lib, Windows: from freeDV)
|
||||
|
||||
# Download alternatives
|
||||
* download from github and build from source
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,29 +0,0 @@
|
|||
e:\funk\hsmodem\hsmodem\debug\vc140.pdb
|
||||
e:\funk\hsmodem\hsmodem\debug\vc140.idb
|
||||
e:\funk\hsmodem\hsmodem\debug\audio.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\audio_voice.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\audio_voice_wasapi.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\audio_wasapi.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\codec2.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\constellation.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\crc16.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\fec.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\fft.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\frame_packer.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\liquid_if.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\main_helper.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\scrambler.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\speed.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\symboltracker.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\udp.obj
|
||||
e:\funk\hsmodem\hsmodem\debug\voiceprocessor.obj
|
||||
e:\funk\hsmodem\debug\hsmodem.ilk
|
||||
e:\funk\hsmodem\debug\hsmodem.exe
|
||||
e:\funk\hsmodem\debug\hsmodem.pdb
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.command.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.read.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\cl.write.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.command.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.read.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\debug\hsmodem.tlog\link.write.1.tlog
|
|
@ -1,22 +0,0 @@
|
|||
liquid_if.cpp
|
||||
hsmodem.cpp
|
||||
fft.cpp
|
||||
audio_wasapi.cpp
|
||||
audio.cpp
|
||||
Code wird generiert...
|
||||
Kompilieren...
|
||||
voiceprocessor.cpp
|
||||
udp.cpp
|
||||
symboltracker.cpp
|
||||
speed.cpp
|
||||
scrambler.cpp
|
||||
main_helper.cpp
|
||||
frame_packer.cpp
|
||||
fec.cpp
|
||||
crc16.cpp
|
||||
constellation.cpp
|
||||
codec2.cpp
|
||||
audio_voice_wasapi.cpp
|
||||
audio_voice.cpp
|
||||
Code wird generiert...
|
||||
hsmodem.vcxproj -> E:\funk\hsmodem\Debug\hsmodem.exe
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,2 +0,0 @@
|
|||
#TargetFrameworkVersion=v4.0:PlatformToolSet=v140_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=8.1
|
||||
Debug|Win32|E:\funk\hsmodem\|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -8,11 +8,12 @@
|
|||
# This will copy the sharded libs to its final location.
|
||||
|
||||
CXXFLAGS = -Wall -O3 -std=c++0x -Wno-write-strings -Wno-narrowing
|
||||
LDFLAGS = -lpthread -lrt -lsndfile -lasound -lm -lopus -lbassopus -lbass -lbassenc_opus -lbassenc -lfftw3 -lfftw3_threads -lliquid -lcodec2
|
||||
OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o audio.o udp.o fft.o liquid_if.o symboltracker.o audio_voice.o voiceprocessor.o codec2.o
|
||||
LDFLAGS = -lpthread -lrt -lsndfile -lasound -lm -lopus -lfftw3 -lfftw3_threads -lliquid -lcodec2 -lsoundio
|
||||
OBJ = hsmodem.o constellation.o crc16.o frame_packer.o main_helper.o scrambler.o speed.o fec.o udp.o fft.o liquid_if.o symboltracker.o voiceprocessor.o codec2.o soundio.o fifo.o announcement.o fifo_voice.o voiceio.o
|
||||
|
||||
default: $(OBJ)
|
||||
mkdir -p ../hsmodemLinux
|
||||
cp ../oscardata/oscardata/bin/Release/oscardata.exe ../hsmodemLinux
|
||||
g++ $(CXXFLAGS) -o ../hsmodemLinux/hsmodem $(OBJ) $(LDFLAGS)
|
||||
|
||||
clean:
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,28 +0,0 @@
|
|||
e:\funk\hsmodem\hsmodem\release\vc140.pdb
|
||||
e:\funk\hsmodem\hsmodem\release\voiceprocessor.obj
|
||||
e:\funk\hsmodem\hsmodem\release\udp.obj
|
||||
e:\funk\hsmodem\hsmodem\release\symboltracker.obj
|
||||
e:\funk\hsmodem\hsmodem\release\speed.obj
|
||||
e:\funk\hsmodem\hsmodem\release\scrambler.obj
|
||||
e:\funk\hsmodem\hsmodem\release\main_helper.obj
|
||||
e:\funk\hsmodem\hsmodem\release\liquid_if.obj
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.obj
|
||||
e:\funk\hsmodem\hsmodem\release\frame_packer.obj
|
||||
e:\funk\hsmodem\hsmodem\release\fft.obj
|
||||
e:\funk\hsmodem\hsmodem\release\fec.obj
|
||||
e:\funk\hsmodem\hsmodem\release\crc16.obj
|
||||
e:\funk\hsmodem\hsmodem\release\constellation.obj
|
||||
e:\funk\hsmodem\hsmodem\release\codec2.obj
|
||||
e:\funk\hsmodem\hsmodem\release\audio_wasapi.obj
|
||||
e:\funk\hsmodem\hsmodem\release\audio_voice_wasapi.obj
|
||||
e:\funk\hsmodem\hsmodem\release\audio_voice.obj
|
||||
e:\funk\hsmodem\hsmodem\release\audio.obj
|
||||
e:\funk\hsmodem\winrelease\hsmodem.exe
|
||||
e:\funk\hsmodem\winrelease\hsmodem.pdb
|
||||
e:\funk\hsmodem\hsmodem\..\winrelease\hsmodem.exe
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.command.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.read.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\cl.write.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.command.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.read.1.tlog
|
||||
e:\funk\hsmodem\hsmodem\release\hsmodem.tlog\link.write.1.tlog
|
|
@ -1,24 +0,0 @@
|
|||
audio.cpp
|
||||
audio_voice.cpp
|
||||
audio_voice_wasapi.cpp
|
||||
audio_wasapi.cpp
|
||||
codec2.cpp
|
||||
constellation.cpp
|
||||
crc16.cpp
|
||||
fec.cpp
|
||||
fft.cpp
|
||||
frame_packer.cpp
|
||||
hsmodem.cpp
|
||||
liquid_if.cpp
|
||||
main_helper.cpp
|
||||
scrambler.cpp
|
||||
speed.cpp
|
||||
symboltracker.cpp
|
||||
udp.cpp
|
||||
voiceprocessor.cpp
|
||||
Code wird generiert.
|
||||
0 of 574 functions ( 0.0%) were compiled, the rest were copied from previous compilation.
|
||||
0 functions were new in current compilation
|
||||
0 functions had inline decision re-evaluated but remain unchanged
|
||||
Codegenerierung ist abgeschlossen.
|
||||
hsmodem.vcxproj -> E:\funk\hsmodem\hsmodem\..\WinRelease\hsmodem.exe
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1,2 +0,0 @@
|
|||
#TargetFrameworkVersion=v4.0:PlatformToolSet=v140_xp:EnableManagedIncrementalBuild=false:VCToolArchitecture=Native32Bit:WindowsTargetPlatformVersion=8.1
|
||||
Release|Win32|E:\funk\hsmodem\|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,127 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* announcement.c ... sends the *.pcm files to the playback device
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
typedef struct _AUDIOFILES_ {
|
||||
char fn[256];
|
||||
int duration;
|
||||
} AUDIOFILES;
|
||||
|
||||
AUDIOFILES audiofiles[12] =
|
||||
{
|
||||
{"amsat", 1100},
|
||||
{"qpsk", 1100},
|
||||
{"psk8", 1100},
|
||||
{"3000", 600},
|
||||
{"4000", 600},
|
||||
{"4410", 900},
|
||||
{"4800", 900},
|
||||
{"5500", 900},
|
||||
{"6000", 600},
|
||||
{"6600", 900},
|
||||
{"7200", 900},
|
||||
{"kbps", 1000},
|
||||
};
|
||||
|
||||
char* getAudiofn(int aidx, char* ext)
|
||||
{
|
||||
static char filename[300];
|
||||
strcpy(filename, "audio/");
|
||||
strcat(filename, audiofiles[aidx].fn);
|
||||
strcat(filename, ext);
|
||||
return filename;
|
||||
}
|
||||
|
||||
void playAudioFLAC(int aidx)
|
||||
{
|
||||
int resamp = 0;
|
||||
int len;
|
||||
int16_t d[100];
|
||||
printf("play:%s, caprate:%d\n", getAudiofn(aidx, ".pcm"),caprate);
|
||||
FILE* fp = fopen(getAudiofn(aidx, ".pcm"), "rb");
|
||||
if (fp)
|
||||
{
|
||||
while ((len = fread(d, sizeof(int16_t), 100, fp)))
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
float f = (float)d[i];
|
||||
f /= 32768;
|
||||
io_pb_write_fifo(f);
|
||||
|
||||
if (caprate == 48000)
|
||||
{
|
||||
if (++resamp >= 9)
|
||||
{
|
||||
resamp = 0;
|
||||
io_pb_write_fifo(f);
|
||||
}
|
||||
}
|
||||
|
||||
// sync with soundcard
|
||||
while (io_pb_fifo_usedspace() > 10000) sleep_ms(1);
|
||||
}
|
||||
if (len != 100) break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
printf("audio file not found\n");
|
||||
}
|
||||
|
||||
int ann_running = 0;
|
||||
int transmissions = 10000;
|
||||
|
||||
void sendAnnouncement()
|
||||
{
|
||||
if (announcement == 0) return;
|
||||
|
||||
if (++transmissions >= announcement)
|
||||
{
|
||||
ann_running = 1;
|
||||
transmissions = 0;
|
||||
|
||||
playAudioFLAC(0);
|
||||
if (bitsPerSymbol == 2) playAudioFLAC(1);
|
||||
else playAudioFLAC(2);
|
||||
switch (linespeed)
|
||||
{
|
||||
case 3000: playAudioFLAC(3); break;
|
||||
case 4000: playAudioFLAC(4); break;
|
||||
case 4410: playAudioFLAC(5); break;
|
||||
case 4800: playAudioFLAC(6); break;
|
||||
case 5500: playAudioFLAC(7); break;
|
||||
case 6000: playAudioFLAC(8); break;
|
||||
case 6600: playAudioFLAC(9); break;
|
||||
case 7200: playAudioFLAC(10); break;
|
||||
}
|
||||
playAudioFLAC(11);
|
||||
|
||||
ann_running = 0;
|
||||
}
|
||||
}
|
|
@ -1,804 +0,0 @@
|
|||
/*
|
||||
* 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.c ... functions to handle audio in/out via a soundcard
|
||||
* uses the "BASS" library
|
||||
*
|
||||
* captures samples from the sound card.
|
||||
* Samples are 32-bit floats in a range of -1 to +1
|
||||
* get these samples from the thread safe fifo: cap_read_fifo(&floatvariable)
|
||||
*
|
||||
* plays samples to the sound card
|
||||
* Samples are 32-bit floats in a range of -1 to +1
|
||||
* play the samples by calling the thread save function: pb_write_fifo(floatsample)
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user);
|
||||
DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *user);
|
||||
int pb_read_fifo(float *data, int elements);
|
||||
void cap_write_fifo(float sample);
|
||||
int pb_fifo_freespace(int nolock);
|
||||
void init_pipes();
|
||||
|
||||
HRECORD rchan = 0; // recording channel
|
||||
BASS_INFO info;
|
||||
HSTREAM stream = 0;
|
||||
|
||||
int openpbdev = -1;
|
||||
int opencapdev = -1;
|
||||
|
||||
float softwareCAPvolume = 0.5;
|
||||
|
||||
void showDeviceInfo(BASS_DEVICEINFO info)
|
||||
{
|
||||
printf("Name:%s driver:%s flags:%d:", info.name, info.driver,info.flags);
|
||||
if (info.flags & BASS_DEVICE_ENABLED) printf("%s\n","BASS_DEVICE_ENABLED ");
|
||||
if (info.flags & BASS_DEVICE_DEFAULT) printf("%s\n","BASS_DEVICE_DEFAULT ");
|
||||
if (info.flags & BASS_DEVICE_INIT) printf("%s\n","BASS_DEVICE_INIT ");
|
||||
if (info.flags & BASS_DEVICE_LOOPBACK) printf("%s\n","BASS_DEVICE_LOOPBACK ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_DIGITAL) printf("%s\n","BASS_DEVICE_TYPE_DIGITAL ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_DISPLAYPORT) printf("%s\n","BASS_DEVICE_TYPE_DISPLAYPORT ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HANDSET) printf("%s\n","BASS_DEVICE_TYPE_HANDSET ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HDMI) printf("%s\n","BASS_DEVICE_TYPE_HDMI ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HEADPHONES) printf("%s\n","BASS_DEVICE_TYPE_HEADPHONES ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HEADSET) printf("%s\n","BASS_DEVICE_TYPE_HEADSET ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_LINE) printf("%s\n","BASS_DEVICE_TYPE_LINE ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_MICROPHONE) printf("%s\n","BASS_DEVICE_TYPE_MICROPHONE ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_NETWORK) printf("%s\n","BASS_DEVICE_TYPE_NETWORK ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_SPDIF) printf("%s\n","BASS_DEVICE_TYPE_SPDIF ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_SPEAKERS) printf("%s\n","BASS_DEVICE_TYPE_SPEAKERS ");
|
||||
|
||||
}
|
||||
|
||||
void showDeviceInfoWasabi(BASS_WASAPI_DEVICEINFO info, int devnum)
|
||||
{
|
||||
printf("%d: Name:%s defperiod:%f flags:%d minperiod:%f mixchans:%d mixfreq:%d type:%d ", devnum, info.name, info.defperiod, info.flags, info.minperiod,info.mixchans, info.mixfreq,info.type);
|
||||
if (info.flags & BASS_DEVICE_ENABLED) printf("%s\n", "BASS_DEVICE_ENABLED ");
|
||||
if (info.flags & BASS_DEVICE_DEFAULT) printf("%s\n", "BASS_DEVICE_DEFAULT ");
|
||||
if (info.flags & BASS_DEVICE_INIT) printf("%s\n", "BASS_DEVICE_INIT ");
|
||||
if (info.flags & BASS_DEVICE_LOOPBACK) printf("%s\n", "BASS_DEVICE_LOOPBACK ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_DIGITAL) printf("%s\n", "BASS_DEVICE_TYPE_DIGITAL ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_DISPLAYPORT) printf("%s\n", "BASS_DEVICE_TYPE_DISPLAYPORT ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HANDSET) printf("%s\n", "BASS_DEVICE_TYPE_HANDSET ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HDMI) printf("%s\n", "BASS_DEVICE_TYPE_HDMI ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HEADPHONES) printf("%s\n", "BASS_DEVICE_TYPE_HEADPHONES ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_HEADSET) printf("%s\n", "BASS_DEVICE_TYPE_HEADSET ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_LINE) printf("%s\n", "BASS_DEVICE_TYPE_LINE ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_MICROPHONE) printf("%s\n", "BASS_DEVICE_TYPE_MICROPHONE ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_NETWORK) printf("%s\n", "BASS_DEVICE_TYPE_NETWORK ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_SPDIF) printf("%s\n", "BASS_DEVICE_TYPE_SPDIF ");
|
||||
if (info.flags & BASS_DEVICE_TYPE_SPEAKERS) printf("%s\n", "BASS_DEVICE_TYPE_SPEAKERS ");
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
uint8_t devstring[MAXDEVSTRLEN +100];
|
||||
char PBdevs[100][256]; // stores the device names, just for diagnosis, has no real fuction
|
||||
char CAPdevs[100][256];
|
||||
|
||||
// index is enumerated number, 0=default
|
||||
AUDIODEVS audioPBdevs[100];
|
||||
AUDIODEVS audioCAPdevs[100];
|
||||
int pbanz = 0, capanz = 0;
|
||||
|
||||
// populate audio device list
|
||||
void readAudioDevs()
|
||||
{
|
||||
int a;
|
||||
pbanz = 0;
|
||||
capanz = 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;
|
||||
for (a = 1; BASS_GetDeviceInfo(a, &info); a++)
|
||||
{
|
||||
//showDeviceInfo(info);
|
||||
if (info.flags & BASS_DEVICE_ENABLED && !(info.flags & BASS_DEVICE_LOOPBACK))
|
||||
{
|
||||
if (!strstr(info.name, "efault"))
|
||||
{
|
||||
audioPBdevs[pbanz].bassdev = a;
|
||||
strncpy(audioPBdevs[pbanz].name, info.name, 255);
|
||||
audioPBdevs[pbanz].name[255] = 0;
|
||||
strncpy(audioPBdevs[pbanz].id, info.driver, 255);
|
||||
pbanz++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (a = 1; BASS_RecordGetDeviceInfo(a, &info); a++)
|
||||
{
|
||||
//showDeviceInfo(info);
|
||||
if (info.flags & BASS_DEVICE_ENABLED && !(info.flags & BASS_DEVICE_LOOPBACK))
|
||||
{
|
||||
if (!strstr(info.name, "efault"))
|
||||
{
|
||||
audioCAPdevs[capanz].bassdev = a;
|
||||
strncpy(audioCAPdevs[capanz].name, info.name, 255);
|
||||
audioCAPdevs[capanz].name[255] = 0;
|
||||
strncpy(audioCAPdevs[capanz].id, info.driver, 255);
|
||||
capanz++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32_
|
||||
BASS_WASAPI_DEVICEINFO info;
|
||||
for (a = 0; BASS_WASAPI_GetDeviceInfo(a, &info); a++)
|
||||
{
|
||||
//showDeviceInfoWasabi(info,a);
|
||||
if (!(info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED) && !(info.flags & BASS_DEVICE_LOOPBACK))
|
||||
{
|
||||
if (!strstr(info.name, "efault"))
|
||||
{
|
||||
audioPBdevs[pbanz].bassdev = a;
|
||||
strncpy(audioPBdevs[pbanz].name, info.name, 255);
|
||||
audioPBdevs[pbanz].name[255] = 0;
|
||||
strncpy(audioPBdevs[pbanz].id, info.id, 255);
|
||||
pbanz++;
|
||||
}
|
||||
}
|
||||
|
||||
if ((info.flags & BASS_DEVICE_INPUT) && (info.flags & BASS_DEVICE_ENABLED) && !(info.flags & BASS_DEVICE_LOOPBACK))
|
||||
{
|
||||
if (!strstr(info.name, "efault"))
|
||||
{
|
||||
audioCAPdevs[capanz].bassdev = a;
|
||||
strncpy(audioCAPdevs[capanz].name, info.name, 255);
|
||||
audioCAPdevs[capanz].name[255] = 0;
|
||||
strncpy(audioCAPdevs[capanz].id, info.id, 255);
|
||||
capanz++;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void printAudioDevs()
|
||||
{
|
||||
printf("PB devices:\n");
|
||||
for (int i = 0; i < pbanz; i++)
|
||||
printf("idx:%d ID:%s bass:%d name:%s\n", i, audioPBdevs[i].id, audioPBdevs[i].bassdev, audioPBdevs[i].name);
|
||||
|
||||
printf("CAP devices:\n");
|
||||
for (int i = 0; i < capanz; i++)
|
||||
printf("idx:%d ID:%s bass:%d name:%s\n", i, audioCAPdevs[i].id, 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
|
||||
devstring[1] = '0' + init_audio_result;
|
||||
devstring[2] = '0' + init_voice_result;
|
||||
|
||||
//printf("init_voice_result:%d\n", devstring[2]);
|
||||
|
||||
|
||||
// playback devices
|
||||
for (int i = 0; i < pbanz; i++)
|
||||
{
|
||||
sprintf((char*)devstring + strlen((char*)devstring), "%d: ", i);
|
||||
strcat((char*)devstring, audioPBdevs[i].name);
|
||||
strcat((char*)devstring, "~"); // audio device separator
|
||||
}
|
||||
|
||||
strcat((char*)(devstring + 1), "^"); // PB, CAP separator
|
||||
|
||||
// capture devices
|
||||
for (int i = 0; i < capanz; i++)
|
||||
{
|
||||
sprintf((char*)devstring + strlen((char*)devstring), "%d: ", i);
|
||||
strcat((char*)devstring, audioCAPdevs[i].name);
|
||||
strcat((char*)devstring, "~"); // audio device separator
|
||||
}
|
||||
|
||||
devstring[0] = 3; // ID for this UDP message
|
||||
}
|
||||
|
||||
uint8_t* getAudioDevicelist(int *len)
|
||||
{
|
||||
// update Status
|
||||
devstring[1] = '0' + init_audio_result;
|
||||
devstring[2] = '0' + init_voice_result;
|
||||
|
||||
*len = strlen((char*)(devstring+1))+1;
|
||||
return devstring;
|
||||
}
|
||||
|
||||
// read audio device list at program start, or if something went wrong
|
||||
void readAudioDevices()
|
||||
{
|
||||
readAudioDevs();
|
||||
//printAudioDevs();
|
||||
buildUdpAudioList();
|
||||
return;
|
||||
}
|
||||
|
||||
// ret: 0=ok, -1=system error, 1=pb error 2=cap error 3=pb+cap error
|
||||
int init_audio(int setpbdev, int setcapdev)
|
||||
{
|
||||
static int f = 1;
|
||||
int ret = 0;
|
||||
|
||||
if (f == 1)
|
||||
{
|
||||
// do only once after program start
|
||||
f = 0;
|
||||
readAudioDevices();
|
||||
init_pipes();
|
||||
}
|
||||
|
||||
// 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 = -2;
|
||||
if (setcapdev >= 0 && setcapdev < capanz) capdev = audioCAPdevs[setcapdev].bassdev;
|
||||
|
||||
printf("init audio, caprate:%d\n",caprate);
|
||||
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);
|
||||
|
||||
// check the correct BASS was loaded
|
||||
if (HIWORD(BASS_GetVersion()) != BASSVERSION)
|
||||
{
|
||||
printf("An incorrect version of BASS was loaded\n");
|
||||
return 3;
|
||||
}
|
||||
|
||||
#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: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number
|
||||
int device = BASS_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbdev = device;
|
||||
openpbdev = pbdev;
|
||||
printf("real BASS PB Device No: %d\n", pbdev);
|
||||
|
||||
// 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 err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number
|
||||
int device = BASS_RecordGetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
capdev = device;
|
||||
printf("real BASS CAP Device No: %d\n", capdev);
|
||||
|
||||
// set capture callback
|
||||
if (rchan) BASS_ChannelStop(rchan);
|
||||
rchan = BASS_RecordStart(caprate, CHANNELS, BASS_SAMPLE_FLOAT, RecordingCallback, 0);
|
||||
if (!rchan)
|
||||
{
|
||||
printf("Can't start capturing: %d\n", BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
opencapdev = capdev;
|
||||
}
|
||||
}
|
||||
|
||||
if(ret == 0)
|
||||
printf("audio started successfully for PBdev:%d and CAPdev:%d\n", openpbdev, opencapdev);
|
||||
else
|
||||
{
|
||||
opencapdev = -1;
|
||||
openpbdev = -1;
|
||||
readAudioDevices();
|
||||
}
|
||||
if (ret == 1)
|
||||
printf("audio initialized: PBerror CapOK\n");
|
||||
if (ret == 2)
|
||||
printf("audio initialized: PBOK CapERROR\n");
|
||||
if (ret == 3)
|
||||
printf("audio initialized: PBerror CapERROR\n");
|
||||
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _LINUX_
|
||||
int selectPBdevice()
|
||||
{
|
||||
if (!BASS_SetDevice(openpbdev))
|
||||
{
|
||||
printf("BASS_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode());
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int selectCAPdevice()
|
||||
{
|
||||
if (!BASS_SetDevice(opencapdev))
|
||||
{
|
||||
//printf("BASS_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode());
|
||||
}
|
||||
else
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void close_audio()
|
||||
{
|
||||
if(stream != 0)
|
||||
{
|
||||
printf("close Audio Devices\n");
|
||||
selectCAPdevice();
|
||||
BASS_ChannelStop(rchan);
|
||||
int rr = BASS_RecordFree();
|
||||
if (!rr) printf("Bass_RecordFree error: %d\n", BASS_ErrorGetCode());
|
||||
|
||||
selectPBdevice();
|
||||
BASS_StreamFree(stream);
|
||||
int r = BASS_Free();
|
||||
if(!r) printf("Bass_Free error: %d\n", BASS_ErrorGetCode());
|
||||
stream = 0;
|
||||
}
|
||||
}
|
||||
|
||||
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 );
|
||||
|
||||
if(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);
|
||||
|
||||
if (selectCAPdevice())
|
||||
{
|
||||
if (!BASS_RecordSetInput(-1, BASS_INPUT_ON, vf))
|
||||
printf("setCAPvolume: %d err:%d\n", opencapdev, BASS_ErrorGetCode());
|
||||
else
|
||||
softwareCAPvolume = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
softwareCAPvolume = (float)v;
|
||||
softwareCAPvolume /= 50;
|
||||
}
|
||||
}
|
||||
|
||||
// capture callback
|
||||
BOOL CALLBACK RecordingCallback(HRECORD handle, const void *buffer, DWORD length, void *user)
|
||||
{
|
||||
//printf("captured %ld samples, channels:%d\n",length/sizeof(float),CHANNELS);
|
||||
//measure_speed(length/sizeof(float));
|
||||
|
||||
float *fbuffer = (float *)buffer;
|
||||
//showbytestringf((char*)"cap:", fbuffer, 10);
|
||||
//printf("w:%ld ",length/sizeof(float));
|
||||
for(unsigned int i=0; i<(length/sizeof(float)); i+=CHANNELS)
|
||||
{
|
||||
//printf("%f\n",fbuffer[i]);
|
||||
cap_write_fifo(fbuffer[i]);
|
||||
}
|
||||
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
// play callback
|
||||
// length: bytes. float=4byte, 2channels, so it requests samples*8
|
||||
DWORD CALLBACK WriteStream(HSTREAM handle, float *buffer, DWORD length, void *user)
|
||||
{
|
||||
//printf("requested %ld samples\n", length / sizeof(float));
|
||||
int ret = pb_read_fifo(buffer, length / sizeof(float));
|
||||
if(ret == 0)
|
||||
{
|
||||
// fifo empty, send 00
|
||||
memset(buffer,0,length);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// 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_
|
||||
CRITICAL_SECTION cap_crit_sec;
|
||||
CRITICAL_SECTION pb_crit_sec;
|
||||
#define CAP_LOCK EnterCriticalSection(&cap_crit_sec)
|
||||
#define PB_LOCK EnterCriticalSection(&pb_crit_sec)
|
||||
void CAP_UNLOCK()
|
||||
{
|
||||
if (&cap_crit_sec != NULL)
|
||||
LeaveCriticalSection(&cap_crit_sec);
|
||||
}
|
||||
void PB_UNLOCK()
|
||||
{
|
||||
if (&pb_crit_sec != NULL)
|
||||
LeaveCriticalSection(&pb_crit_sec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX_
|
||||
pthread_mutex_t cap_crit_sec;
|
||||
pthread_mutex_t pb_crit_sec;
|
||||
#define CAP_LOCK pthread_mutex_lock(&cap_crit_sec)
|
||||
void CAP_UNLOCK() { pthread_mutex_unlock(&cap_crit_sec); }
|
||||
#define PB_LOCK pthread_mutex_lock(&pb_crit_sec)
|
||||
void PB_UNLOCK() { pthread_mutex_unlock(&pb_crit_sec); }
|
||||
#endif
|
||||
|
||||
#define AUDIO_PLAYBACK_BUFLEN (48000 * 10) // space for 10 seconds of samples
|
||||
#define AUDIO_CAPTURE_BUFLEN 24000 // space for 0.5s
|
||||
|
||||
int cap_wridx=0;
|
||||
int cap_rdidx=0;
|
||||
float cap_buffer[AUDIO_CAPTURE_BUFLEN];
|
||||
|
||||
int pb_wridx=0;
|
||||
int pb_rdidx=0;
|
||||
float pb_buffer[AUDIO_PLAYBACK_BUFLEN];
|
||||
|
||||
void init_pipes()
|
||||
{
|
||||
#ifdef _WIN32_
|
||||
if (&cap_crit_sec != NULL) DeleteCriticalSection(&cap_crit_sec);
|
||||
InitializeCriticalSection(&cap_crit_sec);
|
||||
|
||||
if (&pb_crit_sec != NULL) DeleteCriticalSection(&pb_crit_sec);
|
||||
InitializeCriticalSection(&pb_crit_sec);
|
||||
#endif
|
||||
}
|
||||
|
||||
// write one sample into the fifo
|
||||
// overwrite old data if the fifo is full
|
||||
void cap_write_fifo(float sample)
|
||||
{
|
||||
if (((cap_wridx + 1) % AUDIO_CAPTURE_BUFLEN) == cap_rdidx)
|
||||
{
|
||||
printf("cap fifo full\n");
|
||||
}
|
||||
|
||||
CAP_LOCK;
|
||||
cap_buffer[cap_wridx] = sample;
|
||||
if(++cap_wridx >= AUDIO_CAPTURE_BUFLEN) cap_wridx = 0;
|
||||
CAP_UNLOCK();
|
||||
|
||||
// if monitoring is activated then write it also to the voice fifo
|
||||
if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN)
|
||||
toVoice(sample);
|
||||
}
|
||||
|
||||
int cap_read_fifo(float *data)
|
||||
{
|
||||
CAP_LOCK;
|
||||
|
||||
if (cap_rdidx == cap_wridx)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
CAP_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = cap_buffer[cap_rdidx];
|
||||
if(++cap_rdidx >= AUDIO_CAPTURE_BUFLEN) cap_rdidx = 0;
|
||||
CAP_UNLOCK();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cap_write_fifo_clear()
|
||||
{
|
||||
cap_wridx = cap_rdidx = 0;
|
||||
}
|
||||
|
||||
int cap_fifo_freespace()
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
CAP_LOCK;
|
||||
|
||||
int elemInFifo = (cap_wridx + AUDIO_CAPTURE_BUFLEN - cap_rdidx) % AUDIO_CAPTURE_BUFLEN;
|
||||
freebuf = AUDIO_CAPTURE_BUFLEN - elemInFifo;
|
||||
|
||||
CAP_UNLOCK();
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int cap_fifo_usedPercent()
|
||||
{
|
||||
int fs = cap_fifo_freespace();
|
||||
int used = AUDIO_CAPTURE_BUFLEN - fs;
|
||||
used = (used * 100) / AUDIO_CAPTURE_BUFLEN;
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
void pb_write_fifo(float sample)
|
||||
{
|
||||
PB_LOCK;
|
||||
|
||||
// check if there is free space in fifo
|
||||
if(pb_fifo_freespace(1) == 0)
|
||||
{
|
||||
PB_UNLOCK();
|
||||
printf("************* pb fifo full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pb_buffer[pb_wridx] = sample;
|
||||
if(++pb_wridx >= AUDIO_PLAYBACK_BUFLEN) pb_wridx = 0;
|
||||
PB_UNLOCK();
|
||||
//printf("write: pbw:%d pbr:%d\n",pb_wridx,pb_rdidx);
|
||||
}
|
||||
|
||||
void pb_write_fifo_clear()
|
||||
{
|
||||
pb_wridx = pb_rdidx = 0;
|
||||
}
|
||||
|
||||
int pb_fifo_usedBlocks()
|
||||
{
|
||||
int fs = pb_fifo_freespace(0);
|
||||
int used = AUDIO_PLAYBACK_BUFLEN - fs;
|
||||
used /= (txinterpolfactor * UDPBLOCKLEN * 8 / bitsPerSymbol);
|
||||
return used;
|
||||
}
|
||||
|
||||
int pb_fifo_freespace(int nolock)
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
if(nolock == 0) PB_LOCK;
|
||||
|
||||
int elemInFifo = (pb_wridx + AUDIO_PLAYBACK_BUFLEN - pb_rdidx) % AUDIO_PLAYBACK_BUFLEN;
|
||||
freebuf = AUDIO_PLAYBACK_BUFLEN - elemInFifo;
|
||||
|
||||
if(nolock == 0) PB_UNLOCK();
|
||||
|
||||
//printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",AUDIO_PLAYBACK_BUFLEN,pb_wridx,pb_rdidx,freebuf);
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int pb_fifo_usedspace()
|
||||
{
|
||||
int anz = pb_fifo_freespace(0);
|
||||
return AUDIO_PLAYBACK_BUFLEN - anz;
|
||||
}
|
||||
|
||||
// read elements floats from fifo or return 0 if not enough floats are available
|
||||
int pb_read_fifo(float *data, int elements)
|
||||
{
|
||||
//printf("pb read fifo: %d\n",elements);
|
||||
PB_LOCK;
|
||||
|
||||
int e = AUDIO_PLAYBACK_BUFLEN - pb_fifo_freespace(1);
|
||||
if(e < elements)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
PB_UNLOCK();
|
||||
//printf("pb fifo empty: TX underrun\n");
|
||||
//printf("pb fifo empty, need:%d have:%d size:%d\n",elements,e,AUDIO_PLAYBACK_BUFLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i=0; i<elements; i++)
|
||||
{
|
||||
data[i] = pb_buffer[pb_rdidx];
|
||||
if(++pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) pb_rdidx = 0;
|
||||
}
|
||||
//printf("read %d floats\n",elements);
|
||||
|
||||
PB_UNLOCK();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void clear_audio_fifos()
|
||||
{
|
||||
pb_write_fifo_clear();
|
||||
cap_write_fifo_clear();
|
||||
}
|
||||
|
||||
// ================ Play PCM Audio File ===========================
|
||||
|
||||
typedef struct _AUDIOFILES_ {
|
||||
char fn[256];
|
||||
int duration;
|
||||
} AUDIOFILES;
|
||||
|
||||
AUDIOFILES audiofiles[12] =
|
||||
{
|
||||
{"amsat", 1100},
|
||||
{"qpsk", 1100},
|
||||
{"psk8", 1100},
|
||||
{"3000", 600},
|
||||
{"4000", 600},
|
||||
{"4410", 900},
|
||||
{"4800", 900},
|
||||
{"5500", 900},
|
||||
{"6000", 600},
|
||||
{"6600", 900},
|
||||
{"7200", 900},
|
||||
{"kbps", 1000},
|
||||
};
|
||||
|
||||
char* getAudiofn(int aidx, char *ext)
|
||||
{
|
||||
static char filename[300];
|
||||
strcpy(filename, "audio/");
|
||||
strcat(filename, audiofiles[aidx].fn);
|
||||
strcat(filename, ext);
|
||||
return filename;
|
||||
}
|
||||
|
||||
void playAudioFLAC(int aidx)
|
||||
{
|
||||
int resamp = 0;
|
||||
int len;
|
||||
int16_t d[100];
|
||||
printf("play:%s\n", getAudiofn(aidx, ".pcm"));
|
||||
FILE *fp = fopen(getAudiofn(aidx,".pcm"), "rb");
|
||||
if (fp)
|
||||
{
|
||||
while ((len = fread(d, sizeof(int16_t), 100, fp)))
|
||||
{
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
float f = (float)d[i];
|
||||
f /= 32768;
|
||||
pb_write_fifo(f);
|
||||
|
||||
if (caprate == 48000)
|
||||
{
|
||||
if (++resamp >= 9)
|
||||
{
|
||||
resamp = 0;
|
||||
pb_write_fifo(f);
|
||||
}
|
||||
}
|
||||
|
||||
// sync with soundcard
|
||||
while (pb_fifo_usedspace() > 10000) sleep_ms(1);
|
||||
}
|
||||
if (len != 100) break;
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
else
|
||||
printf("audio file not found\n");
|
||||
}
|
||||
|
||||
int ann_running = 0;
|
||||
int transmissions = 10000;
|
||||
|
||||
void sendAnnouncement()
|
||||
{
|
||||
if (announcement == 0) return;
|
||||
|
||||
if (++transmissions >= announcement)
|
||||
{
|
||||
ann_running = 1;
|
||||
transmissions = 0;
|
||||
|
||||
playAudioFLAC(0);
|
||||
if(bitsPerSymbol == 2) playAudioFLAC(1);
|
||||
else playAudioFLAC(2);
|
||||
switch (linespeed)
|
||||
{
|
||||
case 3000: playAudioFLAC(3); break;
|
||||
case 4000: playAudioFLAC(4); break;
|
||||
case 4410: playAudioFLAC(5); break;
|
||||
case 4800: playAudioFLAC(6); break;
|
||||
case 5500: playAudioFLAC(7); break;
|
||||
case 6000: playAudioFLAC(8); break;
|
||||
case 6600: playAudioFLAC(9); break;
|
||||
case 7200: playAudioFLAC(10); break;
|
||||
}
|
||||
playAudioFLAC(11);
|
||||
|
||||
ann_running = 0;
|
||||
}
|
||||
}
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -1,500 +0,0 @@
|
|||
/*
|
||||
* 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.c ... very similar to audio.c but is used for Microphone / Loudspeaker
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
void init_pipes_voice();
|
||||
BOOL CALLBACK RecordingCallback_voice(HRECORD handle, const void* buffer, DWORD length, void* user);
|
||||
DWORD CALLBACK WriteStream_voice(HSTREAM handle, float* buffer, DWORD length, void* user);
|
||||
//void CALLBACK EncodeProc(HENCODE handle, DWORD channel, const void* buffer, DWORD length, void* user);
|
||||
void cap_write_fifo_voice(float sample);
|
||||
int pb_read_fifo_voice(float* data, int elements);
|
||||
void setLSvolume(int v);
|
||||
void setMICvolume(int v);
|
||||
|
||||
extern AUDIODEVS audioPBdevs[100];
|
||||
extern AUDIODEVS audioCAPdevs[100];
|
||||
extern int pbanz;
|
||||
extern int capanz;
|
||||
|
||||
|
||||
HRECORD rchan_voice = 0; // recording channel
|
||||
BASS_INFO info_voice;
|
||||
HSTREAM stream_voice = 0;
|
||||
|
||||
int openpbdev_voice = -1;
|
||||
int opencapdev_voice = -1;
|
||||
int caprate_voice = VOICE_SAMPRATE;
|
||||
|
||||
int initialLSvol = -1;
|
||||
int initialMICvol = -1;
|
||||
|
||||
float softwareCAPvolume_voice = 1;
|
||||
|
||||
// pbdev, capdev: -1=default device
|
||||
int init_audio_voice(int setpbdev, int setcapdev)
|
||||
{
|
||||
static int f = 1;
|
||||
int ret = 0;
|
||||
|
||||
if (f == 1)
|
||||
{
|
||||
// do only once after program start
|
||||
f = 0;
|
||||
init_pipes_voice();
|
||||
}
|
||||
|
||||
// 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 = -2;
|
||||
if (setcapdev >= 0 && setcapdev < capanz) capdev = audioCAPdevs[setcapdev].bassdev;
|
||||
|
||||
printf("voice: init audio_voice, caprate:%d\n", caprate_voice);
|
||||
printf("voice: requested LS device: %d bassno:%d name:%s\n", setpbdev, pbdev, audioPBdevs[setpbdev].name);
|
||||
printf("voice: requested MIC device: %d bassno:%d name:%s\n", setcapdev, capdev, audioCAPdevs[setcapdev].name);
|
||||
|
||||
#ifdef _WIN32_
|
||||
// use WASAPI for Windows to get exclusive access to sound card
|
||||
return init_wasapi_voice(pbdev, capdev);
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX_
|
||||
close_audio_voice();
|
||||
|
||||
if (VoiceAudioMode == 0) return 0; // Voice off
|
||||
|
||||
// ===== PLAYBACK ======
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_Init(pbdev, caprate_voice, 0, NULL, NULL))
|
||||
{
|
||||
printf("voice: Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
close_audio_voice();
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number
|
||||
int device = BASS_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("voice: BASS_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
close_audio_voice();
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbdev = device;
|
||||
openpbdev_voice = pbdev;
|
||||
printf("voice: real BASS PB Device No: %d\n", pbdev);
|
||||
|
||||
// set play callback
|
||||
BASS_GetInfo(&info_voice);
|
||||
stream_voice = BASS_StreamCreate(info_voice.freq, 2, BASS_SAMPLE_FLOAT, (STREAMPROC*)WriteStream_voice, 0); // sample: 32 bit float
|
||||
BASS_ChannelSetAttribute(stream_voice, BASS_ATTRIB_BUFFER, 0); // no buffering for minimum latency
|
||||
BASS_ChannelPlay(stream_voice, FALSE); // start it
|
||||
|
||||
setLSvolume(initialLSvol);
|
||||
}
|
||||
}
|
||||
|
||||
// ===== CAPTURE ====
|
||||
|
||||
// initalize default recording device
|
||||
if (!BASS_RecordInit(capdev))
|
||||
{
|
||||
printf("voice: Can't initialize recording device: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
close_audio_voice();
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number
|
||||
int device = BASS_RecordGetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("voice: BASS_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
close_audio_voice();
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
capdev = device;
|
||||
printf("voice: real BASS CAP Device No: %d\n", capdev);
|
||||
|
||||
// set capture callback
|
||||
rchan_voice = BASS_RecordStart(caprate_voice, 2, BASS_SAMPLE_FLOAT, RecordingCallback_voice, 0);
|
||||
if (!rchan_voice) {
|
||||
printf("voice: Can't start capturing: %d\n", BASS_ErrorGetCode());
|
||||
close_audio_voice();
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
opencapdev_voice = capdev;
|
||||
setMICvolume(initialMICvol);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
printf("voice started successfully for PBdev:%d and CAPdev:%d\n", openpbdev_voice, opencapdev_voice);
|
||||
else
|
||||
{
|
||||
opencapdev_voice = -1;
|
||||
openpbdev_voice = -1;
|
||||
readAudioDevices();
|
||||
}
|
||||
if (ret == 1)
|
||||
printf("voice initialized: PBerror CapOK\n");
|
||||
if (ret == 2)
|
||||
printf("voice initialized: PBOK CapERROR\n");
|
||||
if (ret == 3)
|
||||
printf("voice initialized: PBerror CapERROR\n");
|
||||
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef _LINUX_
|
||||
void selectPBdevice_voice()
|
||||
{
|
||||
if (!BASS_SetDevice(openpbdev_voice))
|
||||
printf("BASS_SetDevice: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
void selectCAPdevice_voice()
|
||||
{
|
||||
if (!BASS_SetDevice(opencapdev_voice))
|
||||
printf("BASS_SetDevice: %d err:%d\n", opencapdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
void close_audio_voice()
|
||||
{
|
||||
printf("voice: close Audio Devices\n");
|
||||
if (stream_voice > 0)
|
||||
BASS_StreamFree(stream_voice);
|
||||
|
||||
if (openpbdev_voice != -1)
|
||||
{
|
||||
selectPBdevice_voice();
|
||||
int r = BASS_Free();
|
||||
if (!r) printf("voice: Bass_Free error: %d\n", BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
if (rchan_voice > 0)
|
||||
BASS_ChannelStop(rchan_voice);
|
||||
|
||||
if (opencapdev_voice != -1)
|
||||
{
|
||||
selectCAPdevice_voice();
|
||||
int rr = BASS_RecordFree();
|
||||
if (!rr) printf("voice: Bass_RecordFree error: %d\n", BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
openpbdev_voice = -1;
|
||||
opencapdev_voice = -1;
|
||||
rchan_voice = 0;
|
||||
stream_voice = 0;
|
||||
}
|
||||
|
||||
void setLSvolume(int v)
|
||||
{
|
||||
if (v < 0 || v>100) return;
|
||||
|
||||
// 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_voice();
|
||||
if (!BASS_SetVolume(vf))
|
||||
printf("setPBvolume: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
void setMICvolume(int v)
|
||||
{
|
||||
if (v < 0 || v>100) return;
|
||||
|
||||
// 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_voice();
|
||||
if (!BASS_RecordSetInput(-1, BASS_INPUT_ON, vf))
|
||||
{
|
||||
printf("setCAPvolume: %d err:%d, using software level\n", opencapdev_voice, BASS_ErrorGetCode());
|
||||
softwareCAPvolume_voice = ((float)v / 100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// capture callback
|
||||
BOOL CALLBACK RecordingCallback_voice(HRECORD handle, const void* buffer, DWORD length, void* user)
|
||||
{
|
||||
//printf("captured %ld samples, channels:%d\n",length/sizeof(float),2);
|
||||
//measure_speed(length/sizeof(float));
|
||||
|
||||
float* fbuffer = (float*)buffer;
|
||||
//showbytestringf((char*)"cap:", fbuffer, 10);
|
||||
//printf("w:%ld ",length/sizeof(float));
|
||||
for (unsigned int i = 0; i < (length / sizeof(float)); i += 2)
|
||||
{
|
||||
//printf("%f\n",fbuffer[i]);
|
||||
cap_write_fifo_voice(fbuffer[i]);
|
||||
}
|
||||
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
// play callback
|
||||
// length: bytes. float=4byte, 2channels, so it requests samples*8
|
||||
DWORD CALLBACK WriteStream_voice(HSTREAM handle, float* buffer, DWORD length, void* user)
|
||||
{
|
||||
//printf("requested %ld samples\n", length / sizeof(float));
|
||||
int ret = pb_read_fifo_voice(buffer, length / sizeof(float));
|
||||
if (ret == 0)
|
||||
{
|
||||
// fifo empty, send 00
|
||||
memset(buffer, 0, length);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// set volume
|
||||
void setVolume_voice(int pbcap, int v)
|
||||
{
|
||||
if (pbcap == 0) setLSvolume(v);
|
||||
else setMICvolume(v);
|
||||
}
|
||||
|
||||
// ================= resampling and other tasks for voice audio =================
|
||||
|
||||
// samples come from the data-audio capture with a speed of caprate
|
||||
// resample (if required) to VOICE_SAMPRATE, which is the voice-audio rate
|
||||
void toVoice(float sample)
|
||||
{
|
||||
if (caprate == VOICE_SAMPRATE)
|
||||
{
|
||||
// resampling not required, just put in LS fifo
|
||||
pb_write_fifo_voice(sample);
|
||||
}
|
||||
else
|
||||
{
|
||||
pb_write_fifo_voice(sample);
|
||||
// samprate of incoming signal is 44100, voice needs 48000
|
||||
// we have 44100 samples/s, so we ar missing 3900 S/s.
|
||||
// if we insert an additional sample every 11 samples
|
||||
// this results in a rate of 48109 S/s
|
||||
static int cnt = 0;
|
||||
if (++cnt >= 11)
|
||||
{
|
||||
cnt = 0;
|
||||
pb_write_fifo_voice(sample);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ================= VOICE FIFOs ===================
|
||||
|
||||
#ifdef _WIN32_
|
||||
CRITICAL_SECTION cap_crit_sec_voice;
|
||||
CRITICAL_SECTION pb_crit_sec_voice;
|
||||
#define CAP_LOCK_VOICE EnterCriticalSection(&cap_crit_sec_voice)
|
||||
#define PB_LOCK_VOICE EnterCriticalSection(&pb_crit_sec_voice)
|
||||
void CAP_UNLOCK_VOICE()
|
||||
{
|
||||
if (&cap_crit_sec_voice != NULL)
|
||||
LeaveCriticalSection(&cap_crit_sec_voice);
|
||||
}
|
||||
void PB_UNLOCK_VOICE()
|
||||
{
|
||||
if (&pb_crit_sec_voice != NULL)
|
||||
LeaveCriticalSection(&pb_crit_sec_voice);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX_
|
||||
pthread_mutex_t cap_crit_sec_voice;
|
||||
pthread_mutex_t pb_crit_sec_voice;
|
||||
#define CAP_LOCK_VOICE pthread_mutex_lock(&cap_crit_sec_voice)
|
||||
void CAP_UNLOCK_VOICE() { pthread_mutex_unlock(&cap_crit_sec_voice); }
|
||||
#define PB_LOCK_VOICE pthread_mutex_lock(&pb_crit_sec_voice)
|
||||
void PB_UNLOCK_VOICE() { pthread_mutex_unlock(&pb_crit_sec_voice); }
|
||||
#endif
|
||||
|
||||
#define AUDIO_PLAYBACK_BUFLEN_VOICE (48000)
|
||||
#define AUDIO_CAPTURE_BUFLEN_VOICE (48000)
|
||||
|
||||
int cap_wridx_voice = 0;
|
||||
int cap_rdidx_voice = 0;
|
||||
float cap_buffer_voice[AUDIO_CAPTURE_BUFLEN_VOICE];
|
||||
|
||||
int pb_wridx_voice = 0;
|
||||
int pb_rdidx_voice = 0;
|
||||
float pb_buffer_voice[AUDIO_PLAYBACK_BUFLEN_VOICE];
|
||||
|
||||
void init_pipes_voice()
|
||||
{
|
||||
#ifdef _WIN32_
|
||||
if (&cap_crit_sec_voice != NULL) DeleteCriticalSection(&cap_crit_sec_voice);
|
||||
InitializeCriticalSection(&cap_crit_sec_voice);
|
||||
|
||||
if (&pb_crit_sec_voice != NULL) DeleteCriticalSection(&pb_crit_sec_voice);
|
||||
InitializeCriticalSection(&pb_crit_sec_voice);
|
||||
#endif
|
||||
}
|
||||
|
||||
// write one sample into the fifo
|
||||
// overwrite old data if the fifo is full
|
||||
void cap_write_fifo_voice(float sample)
|
||||
{
|
||||
if (((cap_wridx_voice + 1) % AUDIO_CAPTURE_BUFLEN_VOICE) == cap_rdidx_voice)
|
||||
{
|
||||
//printf("cap_voice fifo full\n");
|
||||
CAP_UNLOCK_VOICE();
|
||||
return;
|
||||
}
|
||||
|
||||
CAP_LOCK_VOICE;
|
||||
cap_buffer_voice[cap_wridx_voice] = sample;
|
||||
if (++cap_wridx_voice >= AUDIO_CAPTURE_BUFLEN_VOICE) cap_wridx_voice = 0;
|
||||
CAP_UNLOCK_VOICE();
|
||||
}
|
||||
|
||||
int cap_read_fifo_voice(float* data)
|
||||
{
|
||||
CAP_LOCK_VOICE;
|
||||
|
||||
if (cap_rdidx_voice == cap_wridx_voice)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
CAP_UNLOCK_VOICE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = cap_buffer_voice[cap_rdidx_voice];
|
||||
if (++cap_rdidx_voice >= AUDIO_CAPTURE_BUFLEN_VOICE) cap_rdidx_voice = 0;
|
||||
CAP_UNLOCK_VOICE();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void cap_write_fifo_clear_voice()
|
||||
{
|
||||
cap_wridx_voice = cap_rdidx_voice = 0;
|
||||
}
|
||||
|
||||
|
||||
void pb_write_fifo_clear_voice()
|
||||
{
|
||||
pb_wridx_voice = pb_rdidx_voice = 0;
|
||||
}
|
||||
|
||||
int pb_fifo_freespace_voice(int nolock)
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
if (nolock == 0) PB_LOCK_VOICE;
|
||||
|
||||
int elemInFifo = (pb_wridx_voice + AUDIO_PLAYBACK_BUFLEN_VOICE - pb_rdidx_voice) % AUDIO_PLAYBACK_BUFLEN_VOICE;
|
||||
freebuf = AUDIO_PLAYBACK_BUFLEN_VOICE - elemInFifo;
|
||||
|
||||
if (nolock == 0) PB_UNLOCK_VOICE();
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
void pb_write_fifo_voice(float sample)
|
||||
{
|
||||
PB_LOCK_VOICE;
|
||||
|
||||
// check if there is free space in fifo
|
||||
if (pb_fifo_freespace_voice(1) == 0)
|
||||
{
|
||||
PB_UNLOCK_VOICE();
|
||||
//printf("************* pb fifo_voice full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
pb_buffer_voice[pb_wridx_voice] = sample;
|
||||
if (++pb_wridx_voice >= AUDIO_PLAYBACK_BUFLEN_VOICE) pb_wridx_voice = 0;
|
||||
PB_UNLOCK_VOICE();
|
||||
}
|
||||
|
||||
int pb_fifo_usedspace_voice()
|
||||
{
|
||||
int anz = pb_fifo_freespace_voice(0);
|
||||
return AUDIO_PLAYBACK_BUFLEN_VOICE - anz;
|
||||
}
|
||||
|
||||
// read elements floats from fifo or return 0 if not enough floats are available
|
||||
int pb_read_fifo_voice(float* data, int elements)
|
||||
{
|
||||
//printf("pb read fifo_voice: %d\n",elements);
|
||||
PB_LOCK_VOICE;
|
||||
|
||||
int e = AUDIO_PLAYBACK_BUFLEN_VOICE - pb_fifo_freespace_voice(1);
|
||||
if (e < elements)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
PB_UNLOCK_VOICE();
|
||||
//printf("pb fifo empty, need:%d have:%d size:%d\n",elements,e,AUDIO_PLAYBACK_BUFLEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < elements; i+=2)
|
||||
{
|
||||
// channel1 and the same for channel 2
|
||||
data[i] = pb_buffer_voice[pb_rdidx_voice];
|
||||
data[i+1] = pb_buffer_voice[pb_rdidx_voice];
|
||||
if (++pb_rdidx_voice >= AUDIO_PLAYBACK_BUFLEN_VOICE) pb_rdidx_voice = 0;
|
||||
}
|
||||
//printf("read %d floats\n",elements);
|
||||
|
||||
PB_UNLOCK_VOICE();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void clear_voice_fifos()
|
||||
{
|
||||
pb_write_fifo_clear_voice();
|
||||
cap_write_fifo_clear_voice();
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* 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.c ... very similar to audio.c but is used for Microphone / Loudspeaker
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
void cap_write_fifo(float sample);
|
||||
int pb_read_fifo(float* data, int elements);
|
||||
void close_wasapi_voice();
|
||||
DWORD CALLBACK PBcallback_wasapi_voice(void* buffer, DWORD length, void* user);
|
||||
DWORD CALLBACK CAPcallback_wasapi_voice(void* buffer, DWORD length, void* user);
|
||||
void cap_write_fifo_voice(float sample);
|
||||
int pb_read_fifo_voice(float* data, int elements);
|
||||
|
||||
#define WASAPI_CHANNELS_VOICE 2
|
||||
|
||||
float minPBvol_voice = 0;
|
||||
float maxPBvol_voice = 99;
|
||||
float minCAPvol_voice = 0;
|
||||
float maxCAPvol_voice = 99;
|
||||
|
||||
extern int openpbdev_voice;
|
||||
extern int opencapdev_voice;
|
||||
|
||||
extern float softwareCAPvolume_voice;
|
||||
|
||||
int mic_channel_num = 2;
|
||||
|
||||
#ifdef _WIN32_
|
||||
|
||||
int init_wasapi_voice(int pbdev, int capdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
close_wasapi_voice();
|
||||
|
||||
if (VoiceAudioMode == VOICEMODE_OFF) return 0; // Voice off
|
||||
|
||||
// ======= init PLAYBACK device ========
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_WASAPI_Init(pbdev, VOICE_SAMPRATE, WASAPI_CHANNELS_VOICE, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, PBcallback_wasapi_voice, NULL))
|
||||
{
|
||||
printf("Can't initialize wasapi voice output device: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number since a -1 cannot be started
|
||||
int device = BASS_WASAPI_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_WASAPI_GetDevice_voice: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbdev = device;
|
||||
|
||||
// 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());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minPBvol_voice = info.volmin;
|
||||
maxPBvol_voice = info.volmax;
|
||||
|
||||
// start playback
|
||||
if (!BASS_WASAPI_Start())
|
||||
{
|
||||
printf("BASS_WASAPI_Start voice: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
openpbdev_voice = pbdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======= init CAPTURE device ========
|
||||
|
||||
// initalize default recording device
|
||||
if (capdev == -1) capdev = -2; // cap: -2 is the default device for input
|
||||
|
||||
BOOL micret = false;
|
||||
mic_channel_num = 2;
|
||||
micret = BASS_WASAPI_Init(capdev, VOICE_SAMPRATE, mic_channel_num, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, CAPcallback_wasapi_voice, NULL);
|
||||
if (!micret)
|
||||
{
|
||||
micret = BASS_WASAPI_Init(capdev, VOICE_SAMPRATE, 1, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, CAPcallback_wasapi_voice, NULL);
|
||||
if (!micret)
|
||||
{
|
||||
printf("Can't initialize wasapi voice recording device: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
mic_channel_num = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if(micret)
|
||||
{
|
||||
printf("mic opened with %d channels\n", mic_channel_num);
|
||||
// read real device number since a -2 cannot be started
|
||||
int device = BASS_WASAPI_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_WASAPI_GetDevice: voice: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
capdev = device;
|
||||
|
||||
// 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());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
minCAPvol_voice = info.volmin;
|
||||
maxCAPvol_voice = info.volmax;
|
||||
|
||||
// start recording
|
||||
if (!BASS_WASAPI_Start())
|
||||
{
|
||||
printf("BASS_WASAPI_Start voice: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
opencapdev_voice = capdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
printf("wasapi voice started successfully for PBdev:%d and CAPdev:%d\n", openpbdev_voice, opencapdev_voice);
|
||||
else
|
||||
{
|
||||
opencapdev_voice = -1;
|
||||
openpbdev_voice = -1;
|
||||
readAudioDevices();
|
||||
}
|
||||
if (ret == 1)
|
||||
printf("wasapi voice initialized: PBerror CapOK\n");
|
||||
if (ret == 2)
|
||||
printf("wasapi voice initialized: PBOK CapERROR\n");
|
||||
if (ret == 3)
|
||||
printf("wasapi voice initialized: PBerror CapERROR\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int selectPBdevice_wasapi_voice()
|
||||
{
|
||||
if (!BASS_WASAPI_SetDevice(openpbdev_voice))
|
||||
{
|
||||
printf("BASS_WASAPI_SetDevice VOICE: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int selectCAPdevice_wasapi_voice()
|
||||
{
|
||||
if (!BASS_WASAPI_SetDevice(opencapdev_voice))
|
||||
{
|
||||
printf("BASS_WASAPI_SetDevice VOICE: %d err:%d\n", opencapdev_voice, BASS_ErrorGetCode());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void close_wasapi_voice()
|
||||
{
|
||||
printf("close WASAPI Voice Devices\n");
|
||||
|
||||
if (openpbdev_voice != -1)
|
||||
{
|
||||
if(selectPBdevice_wasapi_voice())
|
||||
if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free voice: dev:%d err:%d\n", openpbdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
if (opencapdev_voice != -1)
|
||||
{
|
||||
if(selectCAPdevice_wasapi_voice())
|
||||
if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free voice: dev:%d err:%d\n", opencapdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
printf("closed WASAPI Voice Devices\n");
|
||||
}
|
||||
|
||||
void setLSvolume(int v)
|
||||
{
|
||||
// the volume comes in % 0..99
|
||||
// map to min/maxPBvol
|
||||
float vf = v * (maxPBvol_voice - minPBvol_voice) / 100 + minPBvol_voice;
|
||||
|
||||
if (vf < minPBvol_voice) vf = minPBvol_voice;
|
||||
if (vf > maxPBvol_voice) vf = maxPBvol_voice;
|
||||
|
||||
//printf("set PB volume to:%d / %f [%f..%f]\n", v, vf, minPBvol_voice, maxPBvol_voice);
|
||||
|
||||
if(selectPBdevice_wasapi_voice())
|
||||
if (!BASS_WASAPI_SetVolume(BASS_WASAPI_CURVE_DB, vf))
|
||||
printf("setPBvolume: %d err:%d\n", openpbdev_voice, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
void setMICvolume(int v)
|
||||
{
|
||||
// non of the BASS input level functions are working in WASAPI exclusive mode
|
||||
// so we adjust the input level by software
|
||||
softwareCAPvolume_voice = (float)v;
|
||||
softwareCAPvolume_voice /= 50;
|
||||
}
|
||||
|
||||
DWORD CALLBACK PBcallback_wasapi_voice(void* buffer, DWORD length, void* user)
|
||||
{
|
||||
float* fbuffer = (float*)buffer;
|
||||
int ret = pb_read_fifo_voice(fbuffer, length / sizeof(float));
|
||||
if (ret == 0)
|
||||
{
|
||||
// fifo empty, send 00
|
||||
memset(buffer, 0, length);
|
||||
}
|
||||
return length;
|
||||
}
|
||||
|
||||
DWORD CALLBACK CAPcallback_wasapi_voice(void* buffer, DWORD length, void* user)
|
||||
{
|
||||
float* fbuffer = (float*)buffer;
|
||||
for (unsigned int i = 0; i < (length / sizeof(float)); i += mic_channel_num)
|
||||
{
|
||||
cap_write_fifo_voice(fbuffer[i]);
|
||||
}
|
||||
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,270 +0,0 @@
|
|||
/*
|
||||
* 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 cap_write_fifo(float sample);
|
||||
int pb_read_fifo(float* data, int elements);
|
||||
void close_wasapi();
|
||||
DWORD CALLBACK PBcallback_wasapi(void* buffer, DWORD length, void* user);
|
||||
DWORD CALLBACK CAPcallback_wasapi(void* buffer, DWORD length, void* user);
|
||||
|
||||
float minPBvol = 0;
|
||||
float maxPBvol = 99;
|
||||
float minCAPvol = 0;
|
||||
float maxCAPvol = 99;
|
||||
|
||||
extern int openpbdev;
|
||||
extern int opencapdev;
|
||||
|
||||
int init_wasapi(int pbdev, int capdev)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
close_wasapi();
|
||||
|
||||
// ======= init PLAYBACK device ========
|
||||
|
||||
// initialize default output device
|
||||
if (!BASS_WASAPI_Init(pbdev, caprate, WASAPI_CHANNELS, BASS_WASAPI_EXCLUSIVE, 0.1f, 0, PBcallback_wasapi, NULL))
|
||||
{
|
||||
printf("Can't initialize output device: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number since a -1 cannot be started
|
||||
int device = BASS_WASAPI_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_WASAPI_GetDevice: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
pbdev = device;
|
||||
|
||||
// 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());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
minPBvol = info.volmin;
|
||||
maxPBvol = info.volmax;
|
||||
|
||||
// start playback
|
||||
if (!BASS_WASAPI_Start())
|
||||
{
|
||||
printf("BASS_WASAPI_Start: %d err:%d\n", pbdev, BASS_ErrorGetCode());
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
openpbdev = pbdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ======= 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, 0, CAPcallback_wasapi, NULL))
|
||||
{
|
||||
printf("Can't initialize recording device: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// read real device number since a -2 cannot be started
|
||||
int device = BASS_WASAPI_GetDevice();
|
||||
if (device == -1)
|
||||
{
|
||||
printf("BASS_WASAPI_GetDevice: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
capdev = device;
|
||||
|
||||
// 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());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
minCAPvol = info.volmin;
|
||||
maxCAPvol = info.volmax;
|
||||
|
||||
// start recording
|
||||
if (!BASS_WASAPI_Start())
|
||||
{
|
||||
printf("BASS_WASAPI_Start: %d err:%d\n", capdev, BASS_ErrorGetCode());
|
||||
ret |= 2;
|
||||
}
|
||||
else
|
||||
opencapdev = capdev;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
printf("WASAPI started successfully for PBdev:%d and CAPdev:%d\n", openpbdev, opencapdev);
|
||||
else
|
||||
{
|
||||
opencapdev = -1;
|
||||
openpbdev = -1;
|
||||
readAudioDevices();
|
||||
}
|
||||
if (ret == 1)
|
||||
printf("wasapi audio initialized: PBerror CapOK\n");
|
||||
if (ret == 2)
|
||||
printf("wasapi audio initialized: PBOK CapERROR\n");
|
||||
if (ret == 3)
|
||||
printf("wasapi audio initialized: PBerror CapERROR\n");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int selectPBdevice_wasapi()
|
||||
{
|
||||
if (!BASS_WASAPI_SetDevice(openpbdev))
|
||||
{
|
||||
printf("BASS_WASAPI_SetDevice: %d err:%d\n", openpbdev, BASS_ErrorGetCode());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int selectCAPdevice_wasapi()
|
||||
{
|
||||
if (!BASS_WASAPI_SetDevice(opencapdev))
|
||||
{
|
||||
printf("BASS_WASAPI_SetDevice: %d err:%d\n", opencapdev, BASS_ErrorGetCode());
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
if(selectPBdevice_wasapi())
|
||||
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)
|
||||
{
|
||||
if(selectPBdevice_wasapi())
|
||||
if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", openpbdev, BASS_ErrorGetCode());
|
||||
}
|
||||
|
||||
if (opencapdev != -1)
|
||||
{
|
||||
if(selectCAPdevice_wasapi())
|
||||
if (!BASS_WASAPI_Free()) printf("BASS_WASAPI_Free: dev:%d err:%d\n", opencapdev, BASS_ErrorGetCode());
|
||||
}
|
||||
}
|
||||
|
||||
DWORD CALLBACK PBcallback_wasapi(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_wasapi(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, 10);
|
||||
//printf("%10.6f\n", fbuffer[0]);
|
||||
for (unsigned int i = 0; i < (length / sizeof(float)); i += WASAPI_CHANNELS)
|
||||
{
|
||||
//nullChecker(fbuffer[i],fbuffer, length / sizeof(float));
|
||||
cap_write_fifo(fbuffer[i]);
|
||||
}
|
||||
|
||||
return TRUE; // continue recording
|
||||
}
|
||||
|
||||
#endif // _WIN32_
|
1160
hsmodem/bass.h
1160
hsmodem/bass.h
File diff suppressed because it is too large
Load Diff
BIN
hsmodem/bass.lib
BIN
hsmodem/bass.lib
Binary file not shown.
|
@ -1,207 +0,0 @@
|
|||
/*
|
||||
BASSenc 2.4 C/C++ header file
|
||||
Copyright (c) 2003-2018 Un4seen Developments Ltd.
|
||||
|
||||
See the BASSENC.CHM file for more detailed documentation
|
||||
*/
|
||||
|
||||
#ifndef BASSENC_H
|
||||
#define BASSENC_H
|
||||
|
||||
#include "bass.h"
|
||||
|
||||
#if BASSVERSION!=0x204
|
||||
#error conflicting BASS and BASSenc versions
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef BASSENCDEF
|
||||
#define BASSENCDEF(f) WINAPI f
|
||||
#endif
|
||||
|
||||
typedef DWORD HENCODE; // encoder handle
|
||||
|
||||
// Additional error codes returned by BASS_ErrorGetCode
|
||||
#define BASS_ERROR_ACM_CANCEL 2000 // ACM codec selection cancelled
|
||||
#define BASS_ERROR_CAST_DENIED 2100 // access denied (invalid password)
|
||||
|
||||
// Additional BASS_SetConfig options
|
||||
#define BASS_CONFIG_ENCODE_PRIORITY 0x10300
|
||||
#define BASS_CONFIG_ENCODE_QUEUE 0x10301
|
||||
#define BASS_CONFIG_ENCODE_CAST_TIMEOUT 0x10310
|
||||
|
||||
// Additional BASS_SetConfigPtr options
|
||||
#define BASS_CONFIG_ENCODE_ACM_LOAD 0x10302
|
||||
#define BASS_CONFIG_ENCODE_CAST_PROXY 0x10311
|
||||
|
||||
// BASS_Encode_Start flags
|
||||
#define BASS_ENCODE_NOHEAD 1 // don't send a WAV header to the encoder
|
||||
#define BASS_ENCODE_FP_8BIT 2 // convert floating-point sample data to 8-bit integer
|
||||
#define BASS_ENCODE_FP_16BIT 4 // convert floating-point sample data to 16-bit integer
|
||||
#define BASS_ENCODE_FP_24BIT 6 // convert floating-point sample data to 24-bit integer
|
||||
#define BASS_ENCODE_FP_32BIT 8 // convert floating-point sample data to 32-bit integer
|
||||
#define BASS_ENCODE_FP_AUTO 14 // convert floating-point sample data back to channel's format
|
||||
#define BASS_ENCODE_BIGEND 16 // big-endian sample data
|
||||
#define BASS_ENCODE_PAUSE 32 // start encording paused
|
||||
#define BASS_ENCODE_PCM 64 // write PCM sample data (no encoder)
|
||||
#define BASS_ENCODE_RF64 128 // send an RF64 header
|
||||
#define BASS_ENCODE_MONO 0x100 // convert to mono (if not already)
|
||||
#define BASS_ENCODE_QUEUE 0x200 // queue data to feed encoder asynchronously
|
||||
#define BASS_ENCODE_WFEXT 0x400 // WAVEFORMATEXTENSIBLE "fmt" chunk
|
||||
#define BASS_ENCODE_CAST_NOLIMIT 0x1000 // don't limit casting data rate
|
||||
#define BASS_ENCODE_LIMIT 0x2000 // limit data rate to real-time
|
||||
#define BASS_ENCODE_AIFF 0x4000 // send an AIFF header rather than WAV
|
||||
#define BASS_ENCODE_DITHER 0x8000 // apply dither when converting floating-point sample data to integer
|
||||
#define BASS_ENCODE_AUTOFREE 0x40000 // free the encoder when the channel is freed
|
||||
|
||||
// BASS_Encode_GetACMFormat flags
|
||||
#define BASS_ACM_DEFAULT 1 // use the format as default selection
|
||||
#define BASS_ACM_RATE 2 // only list formats with same sample rate as the source channel
|
||||
#define BASS_ACM_CHANS 4 // only list formats with same number of channels (eg. mono/stereo)
|
||||
#define BASS_ACM_SUGGEST 8 // suggest a format (HIWORD=format tag)
|
||||
|
||||
// BASS_Encode_GetCount counts
|
||||
#define BASS_ENCODE_COUNT_IN 0 // sent to encoder
|
||||
#define BASS_ENCODE_COUNT_OUT 1 // received from encoder
|
||||
#define BASS_ENCODE_COUNT_CAST 2 // sent to cast server
|
||||
#define BASS_ENCODE_COUNT_QUEUE 3 // queued
|
||||
#define BASS_ENCODE_COUNT_QUEUE_LIMIT 4 // queue limit
|
||||
#define BASS_ENCODE_COUNT_QUEUE_FAIL 5 // failed to queue
|
||||
|
||||
// BASS_Encode_CastInit content MIME types
|
||||
#define BASS_ENCODE_TYPE_MP3 "audio/mpeg"
|
||||
#define BASS_ENCODE_TYPE_OGG "audio/ogg"
|
||||
#define BASS_ENCODE_TYPE_AAC "audio/aacp"
|
||||
|
||||
// BASS_Encode_CastGetStats types
|
||||
#define BASS_ENCODE_STATS_SHOUT 0 // Shoutcast stats
|
||||
#define BASS_ENCODE_STATS_ICE 1 // Icecast mount-point stats
|
||||
#define BASS_ENCODE_STATS_ICESERV 2 // Icecast server stats
|
||||
|
||||
typedef void (CALLBACK ENCODEPROC)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, void *user);
|
||||
/* Encoding callback function.
|
||||
handle : The encoder
|
||||
channel: The channel handle
|
||||
buffer : Buffer containing the encoded data
|
||||
length : Number of bytes
|
||||
user : The 'user' parameter value given when starting the encoder */
|
||||
|
||||
typedef void (CALLBACK ENCODEPROCEX)(HENCODE handle, DWORD channel, const void *buffer, DWORD length, QWORD offset, void *user);
|
||||
/* Encoding callback function with offset info.
|
||||
handle : The encoder
|
||||
channel: The channel handle
|
||||
buffer : Buffer containing the encoded data
|
||||
length : Number of bytes
|
||||
offset : File offset of the data
|
||||
user : The 'user' parameter value given when starting the encoder */
|
||||
|
||||
typedef DWORD (CALLBACK ENCODERPROC)(HENCODE handle, DWORD channel, void *buffer, DWORD length, DWORD maxout, void *user);
|
||||
/* Encoder callback function.
|
||||
handle : The encoder
|
||||
channel: The channel handle
|
||||
buffer : Buffer containing the PCM data (input) and receiving the encoded data (output)
|
||||
length : Number of bytes in (-1=closing)
|
||||
maxout : Maximum number of bytes out
|
||||
user : The 'user' parameter value given when calling BASS_Encode_StartUser
|
||||
RETURN : The amount of encoded data (-1=stop) */
|
||||
|
||||
typedef BOOL (CALLBACK ENCODECLIENTPROC)(HENCODE handle, BOOL connect, const char *client, char *headers, void *user);
|
||||
/* Client connection notification callback function.
|
||||
handle : The encoder
|
||||
connect: TRUE/FALSE=client is connecting/disconnecting
|
||||
client : The client's address (xxx.xxx.xxx.xxx:port)
|
||||
headers: Request headers (optionally response headers on return)
|
||||
user : The 'user' parameter value given when calling BASS_Encode_ServerInit
|
||||
RETURN : TRUE/FALSE=accept/reject connection (ignored if connect=FALSE) */
|
||||
|
||||
typedef void (CALLBACK ENCODENOTIFYPROC)(HENCODE handle, DWORD status, void *user);
|
||||
/* Encoder death notification callback function.
|
||||
handle : The encoder
|
||||
status : Notification (BASS_ENCODE_NOTIFY_xxx)
|
||||
user : The 'user' parameter value given when calling BASS_Encode_SetNotify */
|
||||
|
||||
// Encoder notifications
|
||||
#define BASS_ENCODE_NOTIFY_ENCODER 1 // encoder died
|
||||
#define BASS_ENCODE_NOTIFY_CAST 2 // cast server connection died
|
||||
#define BASS_ENCODE_NOTIFY_CAST_TIMEOUT 0x10000 // cast timeout
|
||||
#define BASS_ENCODE_NOTIFY_QUEUE_FULL 0x10001 // queue is out of space
|
||||
#define BASS_ENCODE_NOTIFY_FREE 0x10002 // encoder has been freed
|
||||
|
||||
// BASS_Encode_ServerInit flags
|
||||
#define BASS_ENCODE_SERVER_NOHTTP 1 // no HTTP headers
|
||||
#define BASS_ENCODE_SERVER_META 2 // Shoutcast metadata
|
||||
|
||||
DWORD BASSENCDEF(BASS_Encode_GetVersion)();
|
||||
|
||||
HENCODE BASSENCDEF(BASS_Encode_Start)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user);
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartLimit)(DWORD handle, const char *cmdline, DWORD flags, ENCODEPROC *proc, void *user, DWORD limit);
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartUser)(DWORD handle, const char *filename, DWORD flags, ENCODERPROC *proc, void *user);
|
||||
BOOL BASSENCDEF(BASS_Encode_AddChunk)(HENCODE handle, const char *id, const void *buffer, DWORD length);
|
||||
DWORD BASSENCDEF(BASS_Encode_IsActive)(DWORD handle);
|
||||
BOOL BASSENCDEF(BASS_Encode_Stop)(DWORD handle);
|
||||
BOOL BASSENCDEF(BASS_Encode_StopEx)(DWORD handle, BOOL queue);
|
||||
BOOL BASSENCDEF(BASS_Encode_SetPaused)(DWORD handle, BOOL paused);
|
||||
BOOL BASSENCDEF(BASS_Encode_Write)(DWORD handle, const void *buffer, DWORD length);
|
||||
BOOL BASSENCDEF(BASS_Encode_SetNotify)(DWORD handle, ENCODENOTIFYPROC *proc, void *user);
|
||||
QWORD BASSENCDEF(BASS_Encode_GetCount)(DWORD handle, DWORD count);
|
||||
BOOL BASSENCDEF(BASS_Encode_SetChannel)(DWORD handle, DWORD channel);
|
||||
DWORD BASSENCDEF(BASS_Encode_GetChannel)(HENCODE handle);
|
||||
BOOL BASSENCDEF(BASS_Encode_UserOutput)(DWORD handle, QWORD offset, const void *buffer, DWORD length);
|
||||
|
||||
#ifdef _WIN32
|
||||
DWORD BASSENCDEF(BASS_Encode_GetACMFormat)(DWORD handle, void *form, DWORD formlen, const char *title, DWORD flags);
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartACM)(DWORD handle, const void *form, DWORD flags, ENCODEPROC *proc, void *user);
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartACMFile)(DWORD handle, const void *form, DWORD flags, const char *filename);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartCA)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, ENCODEPROCEX *proc, void *user);
|
||||
HENCODE BASSENCDEF(BASS_Encode_StartCAFile)(DWORD handle, DWORD ftype, DWORD atype, DWORD flags, DWORD bitrate, const char *filename);
|
||||
void *BASSENCDEF(BASS_Encode_GetCARef)(DWORD handle);
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32_WCE
|
||||
BOOL BASSENCDEF(BASS_Encode_CastInit)(HENCODE handle, const char *server, const char *pass, const char *content, const char *name, const char *url, const char *genre, const char *desc, const char *headers, DWORD bitrate, BOOL pub);
|
||||
BOOL BASSENCDEF(BASS_Encode_CastSetTitle)(HENCODE handle, const char *title, const char *url);
|
||||
BOOL BASSENCDEF(BASS_Encode_CastSendMeta)(HENCODE handle, DWORD type, const void *data, DWORD length);
|
||||
const char *BASSENCDEF(BASS_Encode_CastGetStats)(HENCODE handle, DWORD type, const char *pass);
|
||||
|
||||
DWORD BASSENCDEF(BASS_Encode_ServerInit)(HENCODE handle, const char *port, DWORD buffer, DWORD burst, DWORD flags, ENCODECLIENTPROC *proc, void *user);
|
||||
BOOL BASSENCDEF(BASS_Encode_ServerKick)(HENCODE handle, const char *client);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline HENCODE BASS_Encode_Start(DWORD handle, const WCHAR *cmdline, DWORD flags, ENCODEPROC *proc, void *user)
|
||||
{
|
||||
return BASS_Encode_Start(handle, (const char*)cmdline, flags|BASS_UNICODE, proc, user);
|
||||
}
|
||||
|
||||
static inline HENCODE BASS_Encode_StartLimit(DWORD handle, const WCHAR *cmdline, DWORD flags, ENCODEPROC *proc, void *user, DWORD limit)
|
||||
{
|
||||
return BASS_Encode_StartLimit(handle, (const char *)cmdline, flags|BASS_UNICODE, proc, user, limit);
|
||||
}
|
||||
|
||||
static inline HENCODE BASS_Encode_StartUser(DWORD handle, const WCHAR *filename, DWORD flags, ENCODERPROC *proc, void *user)
|
||||
{
|
||||
return BASS_Encode_StartUser(handle, (const char *)filename, flags|BASS_UNICODE, proc, user);
|
||||
}
|
||||
|
||||
static inline DWORD BASS_Encode_GetACMFormat(DWORD handle, void *form, DWORD formlen, const WCHAR *title, DWORD flags)
|
||||
{
|
||||
return BASS_Encode_GetACMFormat(handle, form, formlen, (const char *)title, flags|BASS_UNICODE);
|
||||
}
|
||||
|
||||
static inline HENCODE BASS_Encode_StartACMFile(DWORD handle, const void *form, DWORD flags, const WCHAR *filename)
|
||||
{
|
||||
return BASS_Encode_StartACMFile(handle, form, flags|BASS_UNICODE, (const char *)filename);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,46 +0,0 @@
|
|||
/*
|
||||
BASSenc_OPUS 2.4 C/C++ header file
|
||||
Copyright (c) 2016 Un4seen Developments Ltd.
|
||||
|
||||
See the BASSENC_OPUS.CHM file for more detailed documentation
|
||||
*/
|
||||
|
||||
#ifndef BASSENC_OPUS_H
|
||||
#define BASSENC_OPUS_H
|
||||
|
||||
#include "bassenc.h"
|
||||
|
||||
#if BASSVERSION!=0x204
|
||||
#error conflicting BASS and BASSenc_OPUS versions
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef BASSENCOPUSDEF
|
||||
#define BASSENCOPUSDEF(f) WINAPI f
|
||||
#endif
|
||||
|
||||
DWORD BASSENCOPUSDEF(BASS_Encode_OPUS_GetVersion)();
|
||||
|
||||
HENCODE BASSENCOPUSDEF(BASS_Encode_OPUS_Start)(DWORD handle, const char *options, DWORD flags, ENCODEPROC *proc, void *user);
|
||||
HENCODE BASSENCOPUSDEF(BASS_Encode_OPUS_StartFile)(DWORD handle, const char *options, DWORD flags, const char *filename);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline HENCODE BASS_Encode_OPUS_Start(DWORD handle, const WCHAR *options, DWORD flags, ENCODEPROC *proc, void *user)
|
||||
{
|
||||
return BASS_Encode_OPUS_Start(handle, (const char*)options, flags|BASS_UNICODE, proc, user);
|
||||
}
|
||||
|
||||
static inline HENCODE BASS_Encode_OPUS_StartFile(DWORD handle, const WCHAR *options, DWORD flags, const WCHAR *filename)
|
||||
{
|
||||
return BASS_Encode_OPUS_StartFile(handle, (const char*)options, flags|BASS_UNICODE, (const char*)filename);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
BASSFLAC 2.4 C/C++ header file
|
||||
Copyright (c) 2004-2017 Un4seen Developments Ltd.
|
||||
|
||||
See the BASSFLAC.CHM file for more detailed documentation
|
||||
*/
|
||||
|
||||
#ifndef BASSFLAC_H
|
||||
#define BASSFLAC_H
|
||||
|
||||
#include "bass.h"
|
||||
|
||||
#if BASSVERSION!=0x204
|
||||
#error conflicting BASS and BASSFLAC versions
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef BASSFLACDEF
|
||||
#define BASSFLACDEF(f) WINAPI f
|
||||
#endif
|
||||
|
||||
// BASS_CHANNELINFO type
|
||||
#define BASS_CTYPE_STREAM_FLAC 0x10900
|
||||
#define BASS_CTYPE_STREAM_FLAC_OGG 0x10901
|
||||
|
||||
// Additional tag types
|
||||
#define BASS_TAG_FLAC_CUE 12 // cuesheet : TAG_FLAC_CUE structure
|
||||
#define BASS_TAG_FLAC_PICTURE 0x12000 // + index #, picture : TAG_FLAC_PICTURE structure
|
||||
#define BASS_TAG_FLAC_METADATA 0x12400 // + index #, application metadata : TAG_FLAC_METADATA structure
|
||||
|
||||
typedef struct {
|
||||
DWORD apic; // ID3v2 "APIC" picture type
|
||||
const char *mime; // mime type
|
||||
const char *desc; // description
|
||||
DWORD width;
|
||||
DWORD height;
|
||||
DWORD depth;
|
||||
DWORD colors;
|
||||
DWORD length; // data length
|
||||
const void *data;
|
||||
} TAG_FLAC_PICTURE;
|
||||
|
||||
typedef struct {
|
||||
QWORD offset; // index offset relative to track offset (samples)
|
||||
DWORD number; // index number
|
||||
} TAG_FLAC_CUE_TRACK_INDEX;
|
||||
|
||||
typedef struct {
|
||||
QWORD offset; // track offset (samples)
|
||||
DWORD number; // track number
|
||||
const char *isrc; // ISRC
|
||||
DWORD flags;
|
||||
DWORD nindexes; // number of indexes
|
||||
const TAG_FLAC_CUE_TRACK_INDEX *indexes; // the indexes
|
||||
} TAG_FLAC_CUE_TRACK;
|
||||
|
||||
typedef struct {
|
||||
const char *catalog; // media catalog number
|
||||
DWORD leadin; // lead-in (samples)
|
||||
BOOL iscd; // a CD?
|
||||
DWORD ntracks; // number of tracks
|
||||
const TAG_FLAC_CUE_TRACK *tracks; // the tracks
|
||||
} TAG_FLAC_CUE;
|
||||
|
||||
// TAG_FLAC_CUE_TRACK flags
|
||||
#define TAG_FLAC_CUE_TRACK_DATA 1 // data track
|
||||
#define TAG_FLAC_CUE_TRACK_PRE 2 // pre-emphasis
|
||||
|
||||
typedef struct {
|
||||
char id[4];
|
||||
DWORD length; // data length
|
||||
const void *data;
|
||||
} TAG_FLAC_METADATA;
|
||||
|
||||
HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFile)(BOOL mem, const void *file, QWORD offset, QWORD length, DWORD flags);
|
||||
HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateURL)(const char *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user);
|
||||
HSTREAM BASSFLACDEF(BASS_FLAC_StreamCreateFileUser)(DWORD system, DWORD flags, const BASS_FILEPROCS *procs, void *user);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static inline HSTREAM BASS_FLAC_StreamCreateFile(BOOL mem, const WCHAR *file, QWORD offset, QWORD length, DWORD flags)
|
||||
{
|
||||
return BASS_FLAC_StreamCreateFile(mem, (const void*)file, offset, length, flags|BASS_UNICODE);
|
||||
}
|
||||
|
||||
static inline HSTREAM BASS_FLAC_StreamCreateURL(const WCHAR *url, DWORD offset, DWORD flags, DOWNLOADPROC *proc, void *user)
|
||||
{
|
||||
return BASS_FLAC_StreamCreateURL((const char*)url, offset, flags|BASS_UNICODE, proc, user);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,161 +0,0 @@
|
|||
/*
|
||||
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
|
Binary file not shown.
|
@ -110,7 +110,7 @@ void encode_codec2(float f)
|
|||
f /= 32768;
|
||||
// here we have 8kS/s, need to interpolate to 48 kS/s
|
||||
for(int x=0; x<6; x++)
|
||||
pb_write_fifo_voice(f);
|
||||
io_ls_write_fifo(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ void toCodecDecoder_codec2(uint8_t* pdata, int len)
|
|||
f /= 32768;
|
||||
// here we have 8kS/s, need to interpolate to 48 kS/s
|
||||
for (int x = 0; x < 6; x++)
|
||||
pb_write_fifo_voice(f);
|
||||
io_ls_write_fifo(f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Andrew Kelley
|
||||
*
|
||||
* This file is part of libsoundio, which is MIT licensed.
|
||||
* See http://opensource.org/licenses/MIT
|
||||
*/
|
||||
|
||||
#ifndef SOUNDIO_ENDIAN_H
|
||||
#define SOUNDIO_ENDIAN_H
|
||||
|
||||
#if defined(__BIG_ENDIAN__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__ARMEB__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__THUMBEB__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__AARCH64EB__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(_MIPSEB)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__MIPSEB)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__MIPSEB__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(_BIG_ENDIAN)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__sparc)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__sparc__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(_POWER)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__powerpc__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__ppc__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__hpux)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__hppa)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(_POWER)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__s390__)
|
||||
#define SOUNDIO_OS_BIG_ENDIAN
|
||||
#elif defined(__LITTLE_ENDIAN__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__ARMEL__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__THUMBEL__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__AARCH64EL__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_MIPSEL)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__MIPSEL)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__MIPSEL__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_LITTLE_ENDIAN)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__i386__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__alpha__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__ia64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__ia64__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_M_IX86)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_M_IA64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_M_ALPHA)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__amd64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__amd64__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_M_AMD64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__x86_64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__x86_64__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(_M_X64)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#elif defined(__bfin__)
|
||||
#define SOUNDIO_OS_LITTLE_ENDIAN
|
||||
#else
|
||||
#error unable to detect endianness
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,230 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* fifo.c ... thread safe buffer for audio I/O
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
#ifdef _WIN32_
|
||||
CRITICAL_SECTION io_cap_crit_sec;
|
||||
CRITICAL_SECTION io_pb_crit_sec;
|
||||
#define IO_CAP_LOCK EnterCriticalSection(&io_cap_crit_sec)
|
||||
#define IO_PB_LOCK EnterCriticalSection(&io_pb_crit_sec)
|
||||
void IO_CAP_UNLOCK()
|
||||
{
|
||||
if (&io_cap_crit_sec != NULL)
|
||||
LeaveCriticalSection(&io_cap_crit_sec);
|
||||
}
|
||||
void IO_PB_UNLOCK()
|
||||
{
|
||||
if (&io_pb_crit_sec != NULL)
|
||||
LeaveCriticalSection(&io_pb_crit_sec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX_
|
||||
pthread_mutex_t io_cap_crit_sec;
|
||||
pthread_mutex_t io_pb_crit_sec;
|
||||
#define IO_CAP_LOCK pthread_mutex_lock(&io_cap_crit_sec)
|
||||
void IO_CAP_UNLOCK() { pthread_mutex_unlock(&io_cap_crit_sec); }
|
||||
#define IO_PB_LOCK pthread_mutex_lock(&io_pb_crit_sec)
|
||||
void IO_PB_UNLOCK() { pthread_mutex_unlock(&io_pb_crit_sec); }
|
||||
#endif
|
||||
|
||||
#define AUDIO_PLAYBACK_BUFLEN (48000 * 15) // space for 10 seconds of samples
|
||||
#define AUDIO_CAPTURE_BUFLEN (10000) //48000)// * 10) // space for 10 seconds of samples
|
||||
|
||||
int io_cap_wridx = 0;
|
||||
int io_cap_rdidx = 0;
|
||||
float io_cap_buffer[AUDIO_CAPTURE_BUFLEN];
|
||||
|
||||
int io_pb_wridx = 0;
|
||||
int io_pb_rdidx = 0;
|
||||
float io_pb_buffer[AUDIO_PLAYBACK_BUFLEN];
|
||||
|
||||
void io_init_pipes()
|
||||
{
|
||||
#ifdef _WIN32_
|
||||
if (&io_cap_crit_sec != NULL) DeleteCriticalSection(&io_cap_crit_sec);
|
||||
InitializeCriticalSection(&io_cap_crit_sec);
|
||||
|
||||
if (&io_pb_crit_sec != NULL) DeleteCriticalSection(&io_pb_crit_sec);
|
||||
InitializeCriticalSection(&io_pb_crit_sec);
|
||||
|
||||
io_clear_audio_fifos();
|
||||
#endif
|
||||
|
||||
io_voice_init_pipes();
|
||||
}
|
||||
|
||||
// write one sample into the fifo
|
||||
// overwrite old data if the fifo is full
|
||||
void io_cap_write_fifo(float sample)
|
||||
{
|
||||
if (((io_cap_wridx + 1) % AUDIO_CAPTURE_BUFLEN) == io_cap_rdidx)
|
||||
{
|
||||
printf("cap fifo full\n");
|
||||
}
|
||||
|
||||
IO_CAP_LOCK;
|
||||
io_cap_buffer[io_cap_wridx] = sample;
|
||||
if (++io_cap_wridx >= AUDIO_CAPTURE_BUFLEN) io_cap_wridx = 0;
|
||||
IO_CAP_UNLOCK();
|
||||
|
||||
// if monitoring is activated then write it also to the voice fifo
|
||||
/*if (VoiceAudioMode == VOICEMODE_LISTENAUDIOIN)
|
||||
toVoice(sample);*/
|
||||
}
|
||||
|
||||
int io_cap_read_fifo(float* data)
|
||||
{
|
||||
IO_CAP_LOCK;
|
||||
|
||||
if (io_cap_rdidx == io_cap_wridx)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
IO_CAP_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = io_cap_buffer[io_cap_rdidx];
|
||||
if (++io_cap_rdidx >= AUDIO_CAPTURE_BUFLEN) io_cap_rdidx = 0;
|
||||
IO_CAP_UNLOCK();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void io_cap_write_fifo_clear()
|
||||
{
|
||||
io_cap_wridx = io_cap_rdidx = 0;
|
||||
}
|
||||
|
||||
int io_cap_fifo_freespace()
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
IO_CAP_LOCK;
|
||||
|
||||
int elemInFifo = (io_cap_wridx + AUDIO_CAPTURE_BUFLEN - io_cap_rdidx) % AUDIO_CAPTURE_BUFLEN;
|
||||
freebuf = AUDIO_CAPTURE_BUFLEN - elemInFifo;
|
||||
|
||||
IO_CAP_UNLOCK();
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int io_cap_fifo_usedPercent()
|
||||
{
|
||||
int fs = io_cap_fifo_freespace();
|
||||
int used = AUDIO_CAPTURE_BUFLEN - fs;
|
||||
used = (used * 100) / AUDIO_CAPTURE_BUFLEN;
|
||||
return used;
|
||||
}
|
||||
|
||||
void io_pb_write_fifo(float sample)
|
||||
{
|
||||
IO_PB_LOCK;
|
||||
|
||||
// check if there is free space in fifo
|
||||
if (io_pb_fifo_freespace(1) == 0)
|
||||
{
|
||||
IO_PB_UNLOCK();
|
||||
printf("************* pb fifo full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
io_pb_buffer[io_pb_wridx] = sample;
|
||||
if (++io_pb_wridx >= AUDIO_PLAYBACK_BUFLEN) io_pb_wridx = 0;
|
||||
IO_PB_UNLOCK();
|
||||
//printf("write: pbw:%d pbr:%d\n",io_pb_wridx,io_pb_rdidx);
|
||||
}
|
||||
|
||||
void io_pb_write_fifo_clear()
|
||||
{
|
||||
io_pb_wridx = io_pb_rdidx = 0;
|
||||
}
|
||||
|
||||
int io_pb_fifo_usedBlocks()
|
||||
{
|
||||
int fs = io_pb_fifo_freespace(0);
|
||||
int used = AUDIO_PLAYBACK_BUFLEN - fs;
|
||||
used /= (txinterpolfactor * UDPBLOCKLEN * 8 / bitsPerSymbol);
|
||||
return used;
|
||||
}
|
||||
|
||||
int io_pb_fifo_freespace(int nolock)
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
if (nolock == 0) IO_PB_LOCK;
|
||||
|
||||
int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN;
|
||||
freebuf = AUDIO_PLAYBACK_BUFLEN - elemInFifo;
|
||||
|
||||
if (nolock == 0) IO_PB_UNLOCK();
|
||||
|
||||
//printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",AUDIO_PLAYBACK_BUFLEN,io_pb_wridx,io_pb_rdidx,freebuf);
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int io_pb_fifo_usedspace()
|
||||
{
|
||||
int anz = io_pb_fifo_freespace(0);
|
||||
return AUDIO_PLAYBACK_BUFLEN - anz;
|
||||
}
|
||||
|
||||
// read num elements
|
||||
// if num elems not avail, return 0
|
||||
int io_pb_read_fifo_num(float* data, int num)
|
||||
{
|
||||
IO_PB_LOCK;
|
||||
|
||||
int elemInFifo = (io_pb_wridx + AUDIO_PLAYBACK_BUFLEN - io_pb_rdidx) % AUDIO_PLAYBACK_BUFLEN;
|
||||
|
||||
if (elemInFifo < num)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
//printf("only %d elements available\n", elemInFifo);
|
||||
IO_PB_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
*data++ = io_pb_buffer[io_pb_rdidx];
|
||||
if (++io_pb_rdidx >= AUDIO_PLAYBACK_BUFLEN) io_pb_rdidx = 0;
|
||||
}
|
||||
IO_PB_UNLOCK();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void io_clear_audio_fifos()
|
||||
{
|
||||
io_pb_write_fifo_clear();
|
||||
io_cap_write_fifo_clear();
|
||||
}
|
|
@ -0,0 +1,218 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
* fifo_voice.c ... thread safe buffer for DV audio
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#include "hsmodem.h"
|
||||
|
||||
#ifdef _WIN32_
|
||||
CRITICAL_SECTION io_mic_crit_sec;
|
||||
CRITICAL_SECTION io_ls_crit_sec;
|
||||
#define IO_MIC_LOCK EnterCriticalSection(&io_mic_crit_sec)
|
||||
#define IO_LS_LOCK EnterCriticalSection(&io_ls_crit_sec)
|
||||
void IO_MIC_UNLOCK()
|
||||
{
|
||||
if (&io_mic_crit_sec != NULL)
|
||||
LeaveCriticalSection(&io_mic_crit_sec);
|
||||
}
|
||||
void IO_LS_UNLOCK()
|
||||
{
|
||||
if (&io_ls_crit_sec != NULL)
|
||||
LeaveCriticalSection(&io_ls_crit_sec);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef _LINUX_
|
||||
pthread_mutex_t io_mic_crit_sec;
|
||||
pthread_mutex_t io_ls_crit_sec;
|
||||
#define IO_MIC_LOCK pthread_mutex_lock(&io_mic_crit_sec)
|
||||
void IO_MIC_UNLOCK() { pthread_mutex_unlock(&io_mic_crit_sec); }
|
||||
#define IO_LS_LOCK pthread_mutex_lock(&io_ls_crit_sec)
|
||||
void IO_LS_UNLOCK() { pthread_mutex_unlock(&io_ls_crit_sec); }
|
||||
#endif
|
||||
|
||||
#define VOICE_PLAYBACK_BUFLEN (48000 * 15) // space for 10 seconds of samples
|
||||
#define VOICE_CAPTURE_BUFLEN (10000) //48000)// * 10) // space for 10 seconds of samples
|
||||
|
||||
int io_mic_wridx = 0;
|
||||
int io_mic_rdidx = 0;
|
||||
float io_mic_buffer[VOICE_CAPTURE_BUFLEN];
|
||||
|
||||
int io_ls_wridx = 0;
|
||||
int io_ls_rdidx = 0;
|
||||
float io_ls_buffer[VOICE_PLAYBACK_BUFLEN];
|
||||
|
||||
void io_voice_init_pipes()
|
||||
{
|
||||
#ifdef _WIN32_
|
||||
if (&io_mic_crit_sec != NULL) DeleteCriticalSection(&io_mic_crit_sec);
|
||||
InitializeCriticalSection(&io_mic_crit_sec);
|
||||
|
||||
if (&io_ls_crit_sec != NULL) DeleteCriticalSection(&io_ls_crit_sec);
|
||||
InitializeCriticalSection(&io_ls_crit_sec);
|
||||
|
||||
io_clear_audio_fifos();
|
||||
#endif
|
||||
}
|
||||
|
||||
// write one sample into the fifo
|
||||
// overwrite old data if the fifo is full
|
||||
void io_mic_write_fifo(float sample)
|
||||
{
|
||||
IO_MIC_LOCK;
|
||||
|
||||
if (((io_mic_wridx + 1) % VOICE_CAPTURE_BUFLEN) == io_mic_rdidx)
|
||||
{
|
||||
//printf("mic fifo full\n");
|
||||
IO_MIC_UNLOCK();
|
||||
return;
|
||||
}
|
||||
|
||||
io_mic_buffer[io_mic_wridx] = sample;
|
||||
if (++io_mic_wridx >= VOICE_CAPTURE_BUFLEN) io_mic_wridx = 0;
|
||||
IO_MIC_UNLOCK();
|
||||
}
|
||||
|
||||
int io_mic_read_fifo(float* data)
|
||||
{
|
||||
IO_MIC_LOCK;
|
||||
|
||||
if (io_mic_rdidx == io_mic_wridx)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
IO_MIC_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
*data = io_mic_buffer[io_mic_rdidx];
|
||||
if (++io_mic_rdidx >= VOICE_CAPTURE_BUFLEN) io_mic_rdidx = 0;
|
||||
IO_MIC_UNLOCK();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void io_mic_write_fifo_clear()
|
||||
{
|
||||
io_mic_wridx = io_mic_rdidx = 0;
|
||||
}
|
||||
|
||||
int io_mic_fifo_freespace()
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
IO_MIC_LOCK;
|
||||
|
||||
int elemInFifo = (io_mic_wridx + VOICE_CAPTURE_BUFLEN - io_mic_rdidx) % VOICE_CAPTURE_BUFLEN;
|
||||
freebuf = VOICE_CAPTURE_BUFLEN - elemInFifo;
|
||||
|
||||
IO_MIC_UNLOCK();
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int io_mic_fifo_usedPercent()
|
||||
{
|
||||
int fs = io_mic_fifo_freespace();
|
||||
int used = VOICE_CAPTURE_BUFLEN - fs;
|
||||
used = (used * 100) / VOICE_CAPTURE_BUFLEN;
|
||||
return used;
|
||||
}
|
||||
|
||||
void io_ls_write_fifo_clear()
|
||||
{
|
||||
io_ls_wridx = io_ls_rdidx = 0;
|
||||
}
|
||||
|
||||
int io_ls_fifo_freespace(int nolock)
|
||||
{
|
||||
int freebuf = 0;
|
||||
|
||||
if (nolock == 0) IO_LS_LOCK;
|
||||
|
||||
int elemInFifo = (io_ls_wridx + VOICE_PLAYBACK_BUFLEN - io_ls_rdidx) % VOICE_PLAYBACK_BUFLEN;
|
||||
freebuf = VOICE_PLAYBACK_BUFLEN - elemInFifo;
|
||||
|
||||
if (nolock == 0) IO_LS_UNLOCK();
|
||||
|
||||
//printf("fifolen:%d check: pbw:%d pbr:%d freebuf:%d\n",VOICE_PLAYBACK_BUFLEN,io_ls_wridx,io_ls_rdidx,freebuf);
|
||||
|
||||
return freebuf;
|
||||
}
|
||||
|
||||
int io_ls_fifo_usedspace()
|
||||
{
|
||||
int anz = io_ls_fifo_freespace(0);
|
||||
return VOICE_PLAYBACK_BUFLEN - anz;
|
||||
}
|
||||
|
||||
void io_ls_write_fifo(float sample)
|
||||
{
|
||||
IO_LS_LOCK;
|
||||
|
||||
// check if there is free space in fifo
|
||||
if (io_ls_fifo_freespace(1) == 0)
|
||||
{
|
||||
IO_LS_UNLOCK();
|
||||
printf("************* LS fifo full\n");
|
||||
return;
|
||||
}
|
||||
|
||||
io_ls_buffer[io_ls_wridx] = sample;
|
||||
if (++io_ls_wridx >= VOICE_PLAYBACK_BUFLEN) io_ls_wridx = 0;
|
||||
IO_LS_UNLOCK();
|
||||
}
|
||||
|
||||
// read num elements
|
||||
// if num elems not avail, return 0
|
||||
int io_ls_read_fifo_num(float* data, int num)
|
||||
{
|
||||
IO_LS_LOCK;
|
||||
|
||||
int elemInFifo = (io_ls_wridx + VOICE_PLAYBACK_BUFLEN - io_ls_rdidx) % VOICE_PLAYBACK_BUFLEN;
|
||||
|
||||
if (elemInFifo < num)
|
||||
{
|
||||
// Fifo empty, no data available
|
||||
//printf("only %d elements available\n", elemInFifo);
|
||||
IO_LS_UNLOCK();
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < num; i++)
|
||||
{
|
||||
*data++ = io_ls_buffer[io_ls_rdidx];
|
||||
if (++io_ls_rdidx >= VOICE_PLAYBACK_BUFLEN) io_ls_rdidx = 0;
|
||||
}
|
||||
IO_LS_UNLOCK();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void io_clear_voice_fifos()
|
||||
{
|
||||
io_ls_write_fifo_clear();
|
||||
io_mic_write_fifo_clear();
|
||||
}
|
|
@ -76,7 +76,6 @@ int keeprunning = 1;
|
|||
// UDP I/O
|
||||
int BC_sock_AppToModem = -1;
|
||||
int DATA_sock_AppToModem = -1;
|
||||
//int DATA_sock_from_GR = -1;
|
||||
int DATA_sock_FFT_from_GR = -1;
|
||||
int DATA_sock_I_Q_from_GR = -1;
|
||||
|
||||
|
@ -102,12 +101,16 @@ int txinterpolfactor = 20;
|
|||
int rxPreInterpolfactor = 5;
|
||||
int linespeed = 4410;
|
||||
|
||||
int captureDeviceNo = -1;
|
||||
int playbackDeviceNo = -1;
|
||||
int MicDeviceNo = -1;
|
||||
int LSDeviceNo = -1;
|
||||
int initialPBvol = -1;
|
||||
int initialCAPvol = -1;
|
||||
char captureDeviceName[101] = { 0 };
|
||||
char playbackDeviceName[101] = { 0 };
|
||||
char micDeviceName[101] = { 0 };
|
||||
char lsDeviceName[101] = { 0 };
|
||||
|
||||
float softwareCAPvolume = 1;
|
||||
float softwarePBvolume = 1;
|
||||
float softwareMICvolume = 1;
|
||||
float softwareLSvolume = 1;
|
||||
|
||||
int announcement = 0;
|
||||
int VoiceAudioMode = VOICEMODE_OFF;
|
||||
int codec = 1; // 0=opus, 1=codec2
|
||||
|
@ -174,19 +177,10 @@ int main(int argc, char* argv[])
|
|||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
init_packer();
|
||||
initFEC();
|
||||
init_fft();
|
||||
init_voiceproc();
|
||||
|
||||
/*int ar = init_audio(playbackDeviceNo, captureDeviceNo);
|
||||
if (ar == -1)
|
||||
{
|
||||
keeprunning = 0;
|
||||
exit(0);
|
||||
}*/
|
||||
|
||||
// start udp RX to listen for broadcast search message from Application
|
||||
UdpRxInit(&BC_sock_AppToModem, UdpBCport_AppToModem, &bc_rxdata, &keeprunning);
|
||||
|
@ -194,9 +188,6 @@ int main(int argc, char* argv[])
|
|||
// start udp RX for data from application
|
||||
UdpRxInit(&DATA_sock_AppToModem, UdpDataPort_AppToModem, &appdata_rxdata, &keeprunning);
|
||||
|
||||
// start udp RX to listen for data from GR Receiver
|
||||
//UdpRxInit(&DATA_sock_from_GR, UdpDataPort_fromGR, &GRdata_rxdata, &keeprunning);
|
||||
|
||||
printf("QO100modem initialised and running\n");
|
||||
|
||||
while (keeprunning)
|
||||
|
@ -206,17 +197,15 @@ int main(int argc, char* argv[])
|
|||
startModem();
|
||||
restart_modems = 0;
|
||||
}
|
||||
|
||||
|
||||
//doArraySend();
|
||||
if (VoiceAudioMode == VOICEMODE_INTERNALLOOP)
|
||||
{
|
||||
// loop voice mic to LS
|
||||
float f;
|
||||
if (cap_read_fifo_voice(&f))
|
||||
if (io_mic_read_fifo(&f))
|
||||
{
|
||||
if(softwareCAPvolume_voice >= 0)
|
||||
f *= softwareCAPvolume_voice;
|
||||
pb_write_fifo_voice(f);
|
||||
io_ls_write_fifo(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -224,30 +213,29 @@ int main(int argc, char* argv[])
|
|||
{
|
||||
// send mic to codec
|
||||
float f;
|
||||
if (cap_read_fifo_voice(&f))
|
||||
if (io_mic_read_fifo(&f))
|
||||
{
|
||||
if (softwareCAPvolume_voice >= 0)
|
||||
f *= softwareCAPvolume_voice;
|
||||
encode(f);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// demodulate incoming audio data stream
|
||||
static int old_tm = 0;
|
||||
int tm = getus();
|
||||
if (tm >= (old_tm + 1000000))
|
||||
{
|
||||
// read Audio device list every 1s
|
||||
readAudioDevices();
|
||||
io_readAudioDevices();
|
||||
old_tm = tm;
|
||||
}
|
||||
|
||||
int dret = demodulator();
|
||||
if (dret == 0)
|
||||
{
|
||||
// no new data in fifo
|
||||
// not important how long to sleep, 10ms is fine
|
||||
#ifdef _LINUX_
|
||||
sleep_ms(10);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
printf("stopped: %d\n", keeprunning);
|
||||
|
@ -301,28 +289,29 @@ void startModem()
|
|||
|
||||
// int TX audio and modulator
|
||||
close_dsp();
|
||||
init_audio_result = init_audio(playbackDeviceNo, captureDeviceNo);
|
||||
setPBvolume(initialPBvol);
|
||||
setCAPvolume(initialCAPvol);
|
||||
init_audio_result = io_init_sound(playbackDeviceName, captureDeviceName);
|
||||
init_dsp();
|
||||
}
|
||||
|
||||
void setAudioDevices(int pb, int cap, int pbvol, int capvol, int announce, int pbls, int pbmic)
|
||||
void io_setAudioDevices(uint8_t pbvol, uint8_t capvol, uint8_t announce, uint8_t pbls, uint8_t pbmic, char *pbname, char*capname)
|
||||
{
|
||||
//printf("%d %d\n", pb, cap);
|
||||
|
||||
if (pb != playbackDeviceNo || cap != captureDeviceNo)
|
||||
{
|
||||
restart_modems = 1;
|
||||
playbackDeviceNo = pb;
|
||||
captureDeviceNo = cap;
|
||||
initialPBvol = pbvol;
|
||||
initialCAPvol = capvol;
|
||||
initialLSvol = pbls;
|
||||
initialMICvol = pbmic;
|
||||
}
|
||||
io_setPBvolume(pbvol);
|
||||
io_setCAPvolume(capvol);
|
||||
io_setLSvolume(pbls);
|
||||
io_setMICvolume(pbmic);
|
||||
|
||||
announcement = announce;
|
||||
|
||||
if (strcmp(pbname, playbackDeviceName) || strcmp(captureDeviceName,capname))
|
||||
{
|
||||
restart_modems = 1;
|
||||
|
||||
snprintf(playbackDeviceName, 100, "%s", pbname);
|
||||
playbackDeviceName[99] = 0;
|
||||
|
||||
snprintf(captureDeviceName, 100, "%s", capname);
|
||||
captureDeviceName[99] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// called from UDP RX thread for Broadcast-search from App
|
||||
|
@ -330,7 +319,22 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
{
|
||||
if (len > 0 && pdata[0] == 0x3c)
|
||||
{
|
||||
setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]);
|
||||
/* searchmodem message received
|
||||
* Format:
|
||||
* Byte :
|
||||
* 0 ... 0x3c
|
||||
* 1 ... PB volume
|
||||
* 2 ... CAP volume
|
||||
* 3 ... announcement on / off, duration
|
||||
* 4 ... DV loudspeaker volume
|
||||
* 5 ... DV mic volume
|
||||
* 6..9 ... unused
|
||||
* 10 .. 109 ... PB device name
|
||||
* 110 .. 209 ... CAP device name
|
||||
*/
|
||||
|
||||
//printf("%d %d %d %d %d %d %d \n",pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], pdata[6], pdata[7]);
|
||||
io_setAudioDevices(pdata[1], pdata[2], pdata[3], pdata[4], pdata[5], (char *)(pdata + 10), (char *)(pdata + 110));
|
||||
|
||||
char rxip[20];
|
||||
strcpy(rxip, inet_ntoa(rxsock->sin_addr));
|
||||
|
@ -347,7 +351,7 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
// App searches for the modem IP, mirror the received messages
|
||||
// so the app gets an UDP message with this local IP
|
||||
int alen;
|
||||
uint8_t* txdata = getAudioDevicelist(&alen);
|
||||
uint8_t* txdata = io_getAudioDevicelist(&alen);
|
||||
sendUDP(appIP, UdpDataPort_ModemToApp, txdata, alen);
|
||||
}
|
||||
else
|
||||
|
@ -360,7 +364,7 @@ void bc_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
// App searches for the modem IP, mirror the received messages
|
||||
// so the app gets an UDP message with this local IP
|
||||
int alen;
|
||||
uint8_t* txdata = getAudioDevicelist(&alen);
|
||||
uint8_t* txdata = io_getAudioDevicelist(&alen);
|
||||
sendUDP(appIP, UdpDataPort_ModemToApp, txdata, alen);
|
||||
}
|
||||
}
|
||||
|
@ -432,14 +436,14 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
if (type == 21)
|
||||
{
|
||||
// set playback volume (in % 0..100)
|
||||
setVolume(0,minfo);
|
||||
io_setVolume(0,minfo);
|
||||
return;
|
||||
}
|
||||
|
||||
if (type == 22)
|
||||
{
|
||||
// set capture volume (in % 0..100)
|
||||
setVolume(1,minfo);
|
||||
io_setVolume(1,minfo);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -459,16 +463,35 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
|
||||
if (type == 25)
|
||||
{
|
||||
//printf("%d %d %d %d %d\n", pdata[0], pdata[1], pdata[2], pdata[3], pdata[4]);
|
||||
LSDeviceNo = pdata[1];
|
||||
MicDeviceNo = pdata[2];
|
||||
VoiceAudioMode = pdata[3];
|
||||
codec = pdata[4];
|
||||
/*
|
||||
* Format:
|
||||
* 0 ... statics.SetVoiceMode (25)
|
||||
* 1 ... voicemode
|
||||
* 2 ... codec
|
||||
* 3-102 ... LS device name
|
||||
* 103-202 ... MIC device name
|
||||
*/
|
||||
memcpy(lsDeviceName, pdata + 3, 100);
|
||||
lsDeviceName[99] = 0;
|
||||
memcpy(micDeviceName, pdata + 103, 100);
|
||||
micDeviceName[99] = 0;
|
||||
|
||||
VoiceAudioMode = pdata[1];
|
||||
codec = pdata[2];
|
||||
|
||||
printf("LS:<%s> MIC:<%s> Mode:%d codec:%d\n", lsDeviceName, micDeviceName, VoiceAudioMode, codec);
|
||||
|
||||
// init voice audio
|
||||
init_voice_result = init_audio_voice(LSDeviceNo, MicDeviceNo);
|
||||
init_voiceproc();
|
||||
|
||||
if (VoiceAudioMode == 0)
|
||||
{
|
||||
close_voiceproc();
|
||||
io_close_voice();
|
||||
}
|
||||
else
|
||||
{
|
||||
init_voice_result = io_init_voice(lsDeviceName, micDeviceName);
|
||||
init_voiceproc();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -492,7 +515,7 @@ void appdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock)
|
|||
{
|
||||
// this is the first frame of a larger file
|
||||
sendAnnouncement();
|
||||
// send it multiple times, like a preamble, to give the
|
||||
// send first frame multiple times, like a preamble, to give the
|
||||
// receiver some time for synchronisation
|
||||
// caprate: samples/s. This are symbols: caprate/txinterpolfactor
|
||||
// and bits: symbols * bitsPerSymbol
|
||||
|
|
|
@ -33,9 +33,8 @@
|
|||
#define _USE_MATH_DEFINES
|
||||
#include <math.h>
|
||||
|
||||
#pragma comment(lib, "bass.lib")
|
||||
#pragma comment(lib, "basswasapi.lib")
|
||||
#pragma comment(lib, "libliquid.lib")
|
||||
#pragma comment(lib, "libsoundio.lib")
|
||||
#pragma comment(lib, "fftw_lib/libfftw3-3.lib")
|
||||
#pragma comment(lib, "opus.lib")
|
||||
#pragma comment(lib, "libcodec2.lib")
|
||||
|
@ -57,15 +56,13 @@
|
|||
#endif
|
||||
|
||||
#include "opus.h"
|
||||
#include "bass.h"
|
||||
#include "basswasapi.h"
|
||||
#include "liquid.h"
|
||||
#include "frameformat.h"
|
||||
#include "fec.h"
|
||||
#include "udp.h"
|
||||
#include "symboltracker.h"
|
||||
#include "bassenc_opus.h"
|
||||
#include "codec2.h"
|
||||
#include "soundio.h"
|
||||
|
||||
#define jpg_tempfilename "rxdata.jpg"
|
||||
|
||||
|
@ -74,7 +71,7 @@
|
|||
#define CRC16FILE 2
|
||||
|
||||
// definitions for audio
|
||||
#define MAXDEVSTRLEN 2000
|
||||
#define MAXDEVSTRLEN 5000
|
||||
#define CHANNELS 1 // no of channels used
|
||||
|
||||
// voice audio sampling rate
|
||||
|
@ -120,22 +117,26 @@ void initFEC();
|
|||
void GetFEC(uint8_t* txblock, int len, uint8_t* destArray);
|
||||
int cfec_Reconstruct(uint8_t* darr, uint8_t* destination);
|
||||
|
||||
int init_audio(int pbdev, int capdev);
|
||||
int pb_fifo_freespace(int nolock);
|
||||
int pb_fifo_usedspace();
|
||||
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);
|
||||
void io_pb_write_fifo_clear();
|
||||
int io_init_sound(char* pbname, char* capname);
|
||||
int io_pb_fifo_freespace(int nolock);
|
||||
void io_init_pipes();
|
||||
void io_clear_audio_fifos();
|
||||
void io_close_audio();
|
||||
int io_cap_read_fifo(float* data);
|
||||
void io_readAudioDevices();
|
||||
uint8_t* io_getAudioDevicelist(int* len);
|
||||
void io_pb_write_fifo(float sample);
|
||||
int io_pb_fifo_usedspace();
|
||||
int io_cap_fifo_usedPercent();
|
||||
int io_pb_read_fifo_num(float* data, int num);
|
||||
void io_clear_audio_fifos();
|
||||
void io_setPBvolume(int v);
|
||||
void io_setCAPvolume(int v);
|
||||
void io_setVolume(int pbcap, int v);
|
||||
|
||||
void setVolume_voice(int pbcap, int v);
|
||||
int init_wasapi(int pbdev, int capdev);
|
||||
void sendAnnouncement();
|
||||
void readAudioDevices();
|
||||
void clear_audio_fifos();
|
||||
void clear_voice_fifos();
|
||||
|
||||
void sleep_ms(int ms);
|
||||
int getus();
|
||||
|
@ -143,7 +144,7 @@ void GRdata_rxdata(uint8_t* pdata, int len, struct sockaddr_in* rxsock);
|
|||
void toGR_sendData(uint8_t* data, int type, int status);
|
||||
|
||||
void modulator(uint8_t sym_in);
|
||||
int pb_fifo_usedBlocks();
|
||||
int io_pb_fifo_usedBlocks();
|
||||
void init_dsp();
|
||||
int demodulator();
|
||||
void sendToModulator(uint8_t* d, int len);
|
||||
|
@ -151,32 +152,34 @@ void resetModem();
|
|||
void close_dsp();
|
||||
void init_fft();
|
||||
void exit_fft();
|
||||
void showbytestringf(char* title, float* data, int anz);
|
||||
void showbytestringf(char* title, float* data, int totallen, int anz);
|
||||
uint16_t* make_waterfall(float fre, int* retlen);
|
||||
|
||||
int init_audio_voice(int setpbdev, int setcapdev);
|
||||
void pb_write_fifo_voice(float sample);
|
||||
int cap_read_fifo_voice(float* data);
|
||||
void toVoice(float sample);
|
||||
void toCodecDecoder(uint8_t* pdata, int len);
|
||||
|
||||
void init_voiceproc();
|
||||
void encode(float f);
|
||||
|
||||
int init_wasapi_voice(int pbdev, int capdev);
|
||||
void init_codec2();
|
||||
void encode_codec2(float f);
|
||||
void toCodecDecoder_codec2(uint8_t* pdata, int len);
|
||||
void close_wasapi();
|
||||
void close_wasapi_voice();
|
||||
|
||||
void closeAllandTerminate();
|
||||
void close_voiceproc();
|
||||
void close_codec2();
|
||||
void close_audio();
|
||||
void close_audio_voice();
|
||||
int cap_fifo_usedPercent();
|
||||
|
||||
void io_voice_init_pipes();
|
||||
int io_mic_read_fifo(float* data);
|
||||
void io_ls_write_fifo(float sample);
|
||||
void io_setLSvolume(int v);
|
||||
void io_setMICvolume(int v);
|
||||
char* getDevID(char* devname, int io);
|
||||
int io_init_voice(char* lsname, char* micname);
|
||||
int min_int(int a, int b);
|
||||
void io_close_voice();
|
||||
int io_ls_read_fifo_num(float* data, int num);
|
||||
void io_mic_write_fifo(float sample);
|
||||
void write_sample_s16ne(char* ptr, double sample);
|
||||
|
||||
void km_symtrack_cccf_create(int _ftype,
|
||||
unsigned int _k,
|
||||
|
@ -187,6 +190,7 @@ void km_symtrack_cccf_reset(int mode);
|
|||
void km_symtrack_cccf_set_bandwidth(float _bw);
|
||||
void km_symtrack_execute(liquid_float_complex _x, liquid_float_complex* _y, unsigned int* _ny, unsigned int* psym_out);
|
||||
|
||||
|
||||
extern int speedmode;
|
||||
extern int bitsPerSymbol;
|
||||
extern int constellationSize;
|
||||
|
@ -200,7 +204,7 @@ extern int txinterpolfactor;
|
|||
extern int rxPreInterpolfactor;
|
||||
extern char appIP[20];
|
||||
extern float softwareCAPvolume;
|
||||
extern float softwareCAPvolume_voice;
|
||||
extern float softwarePBvolume;
|
||||
extern int announcement;
|
||||
extern int ann_running;
|
||||
extern int transmissions;
|
||||
|
@ -216,13 +220,8 @@ extern int codec;
|
|||
extern int trigger_resetmodem;
|
||||
extern int rxlevel_deteced;
|
||||
extern int rx_in_sync;
|
||||
|
||||
// audio device description table
|
||||
typedef struct {
|
||||
int bassdev; // bass (basswasapi) dev no
|
||||
char name[256]; // DEV name
|
||||
char id[256];
|
||||
} AUDIODEVS;
|
||||
extern float softwareMICvolume;
|
||||
extern float softwareLSvolume;
|
||||
|
||||
#ifdef _LINUX_
|
||||
int isRunning(char* prgname);
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue