This commit is contained in:
Kurt Moraw 2020-12-10 19:14:40 +01:00
parent cedbae4628
commit 6adaf44425
129 changed files with 4885 additions and 4078 deletions

View File

@ -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.

BIN
WinRelease/libsoundio.dll Executable file

Binary file not shown.

Binary file not shown.

1043
hsmodem.wse Executable file

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.

View File

@ -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

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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

View File

@ -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.

View File

@ -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.

127
hsmodem/announcement.cpp Executable file
View File

@ -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;
}
}

View File

@ -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;
}
}

BIN
hsmodem/audio/sound0.pcm Normal file

Binary file not shown.

BIN
hsmodem/audio/sound1.pcm Normal file

Binary file not shown.

View File

@ -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();
}

View File

@ -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

View File

@ -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_

File diff suppressed because it is too large Load Diff

Binary file not shown.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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);
}
}
}

97
hsmodem/endian.h Normal file
View File

@ -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

230
hsmodem/fifo.cpp Executable file
View File

@ -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();
}

218
hsmodem/fifo_voice.cpp Executable file
View File

@ -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();
}

View File

@ -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

View File

@ -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