SSB_HighSpeed_Modem/hsmodem/libkmaudio/libkmaudio_interface.cpp

169 lines
3.9 KiB
C++
Executable File

#include "libkmaudio.h"
void getMax(int id, float fv);
void close_stream(int id)
{
#ifdef WIN32
if (devlist[id].capStream != NULL)
close_capture_stream(id);
if (devlist[id].pbStream != NULL)
close_playback_stream(id);
#else
if (devlist[id].instream != NULL)
close_capture_stream(id);
if (devlist[id].outstream != NULL)
close_playback_stream(id);
#endif
}
/*
* reads len samples from device id into psamp
* returns: number of values written to psamp , -1=error
* id ... device id returned by kmaudio_startCapture
* psamp ... float array of length len getting the audio data (mono)
* len ... number of float values to write into psamp
* volume ... 0.0f..2.0f will be multiplied with the input sample
* wait ... 1=wait for data, 0=return if not enough data available (in this case psamp will return 0,0,0...)
*
* if resampling is required the number of returned samples may differ from the number of requested samples
* it can be larger, so the buffer psamp should be larger than "len" by factor 1.1
*/
int kmaudio_readsamples(int id, float* psamp, int len, float volume, int wait)
{
int e = io_fifo_elems_avail(id);
if (e < len) return 0;
if (devlist[id].requested_samprate == devlist[id].real_samprate)
{
// data rate is ok, take samples as is
int nl = io_read_fifo_num(id, psamp, len);
for (int i = 0; i < nl; i++)
{
psamp[i] *= volume;
getMax(id, psamp[i]);
//kmaudio_detectDropouts(id);
}
return nl;
}
// resampling is required
int num = io_read_fifo_num(id, psamp, len);
if (num == 0) return 0;
int newlen = 0;
float *f = resample(id, psamp, len, &newlen);
for (int i = 0; i < newlen; i++)
{
psamp[i] = f[i] * volume;
getMax(id, psamp[i]);
}
return newlen;
}
/*
* plays len samples from psamp to device id
* returns: 0=ok, -1=error
* id ... device id returned by kmaudio_startPlayback
* psamp ... float array of length len with the audio data (mono)
* len ... number of float values in psamp
* volume ... 0.0f..2.0f will be multiplied with the output sample
*/
int kmaudio_playsamples(int id, float* psamp, int len, float volume)
{
// check if resampling is required
//printf("%d %d\n", devlist[id].requested_samprate , devlist[id].real_samprate);
if (devlist[id].requested_samprate == devlist[id].real_samprate)
{
// sampling rate is ok, just play samples
for (int i = 0; i < len; i++)
{
io_write_fifo(id, psamp[i] * volume);
getMax(id, psamp[i] * volume);
}
return 0;
}
// resampling is required
int newlen = 0;
float *f = resample(id, psamp, len, &newlen);
for (int i = 0; i < newlen; i++)
{
io_write_fifo(id, f[i] * volume);
getMax(id, psamp[i] * volume);
}
return 0;
}
#define MCHECK 48000 // abt. 1s of samples
float farr[MAXDEVICES][MCHECK];
int farridx[MAXDEVICES];
void init_maxarray()
{
// initialize arrays
for (int md = 0; md < MAXDEVICES; md++)
{
farridx[md] = 0;
for (int i = 0; i < MCHECK; i++)
farr[md][i] = 0;
}
}
void getMax(int id, float fv)
{
// put value into array
farr[id][farridx[id]] = fv;
if (++farridx[id] == MCHECK)
farridx[id] = 0;
}
/*
* returns the max level (within 1 second) of this stream in % (0..100)
* if the level >= 100 the signal will get clipped and distorted
*/
uint8_t kmaudio_maxlevel(int id)
{
float max = 0;
for (int i = 0; i < MCHECK; i++)
if (farr[id][i] > max) max = farr[id][i];
return (uint8_t)(max * 100);
}
void kmaudio_detectDropouts(int id)
{
int stat = 0;
int drlen = 0;
for (int i = 0; i < MCHECK; i++)
{
switch (stat)
{
case 0: // search beginning of dropout
if (farr[id][i] == 0.0f)
stat = 1;
break;
case 1: // count length of dropout
if (farr[id][i] == 0.0f) drlen++;
else
{
// end of dropout
if (drlen > 0)
{
printf("Dropout len:%d\n", drlen);
}
drlen = 0;
stat = 0;
}
break;
}
}
}