1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2025-09-05 14:47:50 -04:00

DSD demod plugin: DSD proper integration interim state #1

This commit is contained in:
f4exb 2016-04-09 13:12:48 +02:00
parent 9ef7497c40
commit 5872ee0ca7
10 changed files with 526 additions and 403 deletions

View File

@ -17,424 +17,433 @@
#include "dsd.h" #include "dsd.h"
void void processAudio(dsd_opts * opts, dsd_state * state)
processAudio (dsd_opts * opts, dsd_state * state)
{ {
int i, n; int i, n;
float aout_abs, max, gainfactor, gaindelta, maxbuf; float aout_abs, max, gainfactor, gaindelta, maxbuf;
if (opts->audio_gain == (float) 0) if (opts->audio_gain == (float) 0)
{ {
// detect max level // detect max level
max = 0; max = 0;
state->audio_out_temp_buf_p = state->audio_out_temp_buf; state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++) for (n = 0; n < 160; n++)
{ {
aout_abs = fabsf (*state->audio_out_temp_buf_p); aout_abs = fabsf(*state->audio_out_temp_buf_p);
if (aout_abs > max) if (aout_abs > max)
{ {
max = aout_abs; max = aout_abs;
} }
state->audio_out_temp_buf_p++; state->audio_out_temp_buf_p++;
} }
*state->aout_max_buf_p = max; *state->aout_max_buf_p = max;
state->aout_max_buf_p++; state->aout_max_buf_p++;
state->aout_max_buf_idx++; state->aout_max_buf_idx++;
if (state->aout_max_buf_idx > 24) if (state->aout_max_buf_idx > 24)
{ {
state->aout_max_buf_idx = 0; state->aout_max_buf_idx = 0;
state->aout_max_buf_p = state->aout_max_buf; state->aout_max_buf_p = state->aout_max_buf;
} }
// lookup max history // lookup max history
for (i = 0; i < 25; i++) for (i = 0; i < 25; i++)
{ {
maxbuf = state->aout_max_buf[i]; maxbuf = state->aout_max_buf[i];
if (maxbuf > max) if (maxbuf > max)
{ {
max = maxbuf; max = maxbuf;
} }
} }
// determine optimal gain level // determine optimal gain level
if (max > (float) 0) if (max > (float) 0)
{ {
gainfactor = ((float) 30000 / max); gainfactor = ((float) 30000 / max);
} }
else else
{ {
gainfactor = (float) 50; gainfactor = (float) 50;
} }
if (gainfactor < state->aout_gain) if (gainfactor < state->aout_gain)
{ {
state->aout_gain = gainfactor; state->aout_gain = gainfactor;
gaindelta = (float) 0; gaindelta = (float) 0;
} }
else else
{ {
if (gainfactor > (float) 50) if (gainfactor > (float) 50)
{ {
gainfactor = (float) 50; gainfactor = (float) 50;
} }
gaindelta = gainfactor - state->aout_gain; gaindelta = gainfactor - state->aout_gain;
if (gaindelta > ((float) 0.05 * state->aout_gain)) if (gaindelta > ((float) 0.05 * state->aout_gain))
{ {
gaindelta = ((float) 0.05 * state->aout_gain); gaindelta = ((float) 0.05 * state->aout_gain);
} }
} }
gaindelta /= (float) 160; gaindelta /= (float) 160;
} }
else else
{ {
gaindelta = (float) 0; gaindelta = (float) 0;
} }
if(opts->audio_gain >= 0){ if (opts->audio_gain >= 0)
// adjust output gain {
// adjust output gain
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
*state->audio_out_temp_buf_p = (state->aout_gain
+ ((float) n * gaindelta)) * (*state->audio_out_temp_buf_p);
state->audio_out_temp_buf_p++;
}
state->aout_gain += ((float) 160 * gaindelta);
}
// copy audio datat to output buffer and upsample if necessary
state->audio_out_temp_buf_p = state->audio_out_temp_buf; state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++) if ((opts->split == 0) || (opts->upsample))
{
*state->audio_out_temp_buf_p = (state->aout_gain + ((float) n * gaindelta)) * (*state->audio_out_temp_buf_p);
state->audio_out_temp_buf_p++;
}
state->aout_gain += ((float) 160 * gaindelta);
}
// copy audio datat to output buffer and upsample if necessary
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
if (opts->split == 0)
{ {
for (n = 0; n < 160; n++) for (n = 0; n < 160; n++)
{ {
upsample (state, *state->audio_out_temp_buf_p); upsample(state, *state->audio_out_temp_buf_p);
state->audio_out_temp_buf_p++; state->audio_out_temp_buf_p++;
state->audio_out_float_buf_p += 6; state->audio_out_float_buf_p += 6;
state->audio_out_idx += 6; state->audio_out_idx += 6;
state->audio_out_idx2 += 6; state->audio_out_idx2 += 6;
} }
state->audio_out_float_buf_p -= (960 + opts->playoffset); state->audio_out_float_buf_p -= (960 + opts->playoffset);
// copy to output (short) buffer // copy to output (short) buffer
for (n = 0; n < 960; n++) for (n = 0; n < 960; n++)
{ {
if (*state->audio_out_float_buf_p > (float) 32760) if (*state->audio_out_float_buf_p > (float) 32760)
{ {
*state->audio_out_float_buf_p = (float) 32760; *state->audio_out_float_buf_p = (float) 32760;
} }
else if (*state->audio_out_float_buf_p < (float) -32760) else if (*state->audio_out_float_buf_p < (float) -32760)
{ {
*state->audio_out_float_buf_p = (float) -32760; *state->audio_out_float_buf_p = (float) -32760;
} }
*state->audio_out_buf_p = (short) *state->audio_out_float_buf_p; *state->audio_out_buf_p = (short) *state->audio_out_float_buf_p;
state->audio_out_buf_p++; state->audio_out_buf_p++;
state->audio_out_float_buf_p++; state->audio_out_float_buf_p++;
} }
state->audio_out_float_buf_p += opts->playoffset; state->audio_out_float_buf_p += opts->playoffset;
} }
else else
{ {
for (n = 0; n < 160; n++) for (n = 0; n < 160; n++)
{ {
if (*state->audio_out_temp_buf_p > (float) 32760) if (*state->audio_out_temp_buf_p > (float) 32760)
{ {
*state->audio_out_temp_buf_p = (float) 32760; *state->audio_out_temp_buf_p = (float) 32760;
} }
else if (*state->audio_out_temp_buf_p < (float) -32760) else if (*state->audio_out_temp_buf_p < (float) -32760)
{ {
*state->audio_out_temp_buf_p = (float) -32760; *state->audio_out_temp_buf_p = (float) -32760;
} }
*state->audio_out_buf_p = (short) *state->audio_out_temp_buf_p; *state->audio_out_buf_p = (short) *state->audio_out_temp_buf_p;
state->audio_out_buf_p++; state->audio_out_buf_p++;
state->audio_out_temp_buf_p++; state->audio_out_temp_buf_p++;
state->audio_out_idx++; state->audio_out_idx++;
state->audio_out_idx2++; state->audio_out_idx2++;
} }
} }
} }
void void writeSynthesizedVoice(dsd_opts * opts, dsd_state * state)
writeSynthesizedVoice (dsd_opts * opts, dsd_state * state)
{ {
#ifdef USE_LIBSNDFILE #ifdef USE_LIBSNDFILE
int n; int n;
short aout_buf[160]; short aout_buf[160];
short *aout_buf_p; short *aout_buf_p;
// for(n=0; n<160; n++) // for(n=0; n<160; n++)
// fprintf(stderr, "%d ", ((short*)(state->audio_out_temp_buf))[n]); // fprintf(stderr, "%d ", ((short*)(state->audio_out_temp_buf))[n]);
// fprintf(stderr, "\n"); // fprintf(stderr, "\n");
aout_buf_p = aout_buf; aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf; state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++) for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_p > (float) 32767)
{
*state->audio_out_temp_buf_p = (float) 32767;
}
else if (*state->audio_out_temp_buf_p < (float) -32768)
{
*state->audio_out_temp_buf_p = (float) -32768;
}
*aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++;
state->audio_out_temp_buf_p++;
}
sf_write_short(opts->wav_out_f, aout_buf, 160);
/*
int n;
short aout_buf[160];
short *aout_buf_p;
ssize_t result;
aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{ {
if (*state->audio_out_temp_buf_p > (float) 32760) if (*state->audio_out_temp_buf_p > (float) 32767)
{ {
*state->audio_out_temp_buf_p = (float) 32760; *state->audio_out_temp_buf_p = (float) 32767;
} }
else if (*state->audio_out_temp_buf_p < (float) -32760) else if (*state->audio_out_temp_buf_p < (float) -32768)
{ {
*state->audio_out_temp_buf_p = (float) -32760; *state->audio_out_temp_buf_p = (float) -32768;
} }
*aout_buf_p = (short) *state->audio_out_temp_buf_p; *aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++; aout_buf_p++;
state->audio_out_temp_buf_p++; state->audio_out_temp_buf_p++;
} }
result = write (opts->wav_out_fd, aout_buf, 320); sf_write_short(opts->wav_out_f, aout_buf, 160);
fflush (opts->wav_out_f); /*
state->wav_out_bytes += 320;
*/ int n;
short aout_buf[160];
short *aout_buf_p;
ssize_t result;
aout_buf_p = aout_buf;
state->audio_out_temp_buf_p = state->audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
if (*state->audio_out_temp_buf_p > (float) 32760)
{
*state->audio_out_temp_buf_p = (float) 32760;
}
else if (*state->audio_out_temp_buf_p < (float) -32760)
{
*state->audio_out_temp_buf_p = (float) -32760;
}
*aout_buf_p = (short) *state->audio_out_temp_buf_p;
aout_buf_p++;
state->audio_out_temp_buf_p++;
}
result = write (opts->wav_out_fd, aout_buf, 320);
fflush (opts->wav_out_f);
state->wav_out_bytes += 320;
*/
#endif #endif
} }
void void playSynthesizedVoice(dsd_opts * opts, dsd_state * state)
playSynthesizedVoice (dsd_opts * opts, dsd_state * state)
{ {
ssize_t result; ssize_t result;
if (state->audio_out_idx > opts->delay) if (state->audio_out_idx > opts->delay)
{ {
// output synthesized speech to sound card // output synthesized speech to sound card
if (opts->audio_out_fd == -1) if (opts->audio_out_fd == -1)
{ {
memcpy(state->output_buffer + state->output_offset, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2)); memcpy(state->output_buffer + state->output_offset,
state->output_offset += state->audio_out_idx; (state->audio_out_buf_p - state->audio_out_idx),
(state->audio_out_idx * 2));
state->output_offset += state->audio_out_idx;
} }
else else
{ {
result = write (opts->audio_out_fd, (state->audio_out_buf_p - state->audio_out_idx), (state->audio_out_idx * 2)); result = write(opts->audio_out_fd,
(state->audio_out_buf_p - state->audio_out_idx),
(state->audio_out_idx * 2));
} }
state->audio_out_idx = 0; state->audio_out_idx = 0;
} }
if (state->audio_out_idx2 >= 800000) if (state->audio_out_idx2 >= 800000)
{ {
state->audio_out_float_buf_p = state->audio_out_float_buf + 100; state->audio_out_float_buf_p = state->audio_out_float_buf + 100;
state->audio_out_buf_p = state->audio_out_buf + 100; state->audio_out_buf_p = state->audio_out_buf + 100;
memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); memset(state->audio_out_float_buf, 0, 100 * sizeof(float));
memset (state->audio_out_buf, 0, 100 * sizeof (short)); memset(state->audio_out_buf, 0, 100 * sizeof(short));
state->audio_out_idx2 = 0; state->audio_out_idx2 = 0;
} }
} }
void void openAudioOutDevice(dsd_opts * opts, int speed)
openAudioOutDevice (dsd_opts * opts, int speed)
{ {
// get info of device/file // get info of device/file
struct stat stat_buf; struct stat stat_buf;
if(stat(opts->audio_out_dev, &stat_buf) != 0) { if (stat(opts->audio_out_dev, &stat_buf) != 0)
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev);
exit(1);
}
if( !(S_ISCHR(stat_buf.st_mode) || S_ISBLK(stat_buf.st_mode))) { // this is not a device
fprintf(stderr, "Error, %s is not a device. use -w filename for wav output.\n", opts->audio_out_dev);
exit(1);
}
#ifdef SOLARIS
sample_info_t aset, aget;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{ {
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev); fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev);
exit (1); exit(1);
} }
// get current if (!(S_ISCHR(stat_buf.st_mode) || S_ISBLK(stat_buf.st_mode)))
ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset); { // this is not a device
fprintf(stderr,
aset.record.sample_rate = speed; "Error, %s is not a device. use -w filename for wav output.\n",
aset.play.sample_rate = speed; opts->audio_out_dev);
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
{
fprintf(stderr, "Error setting sample device parameters\n");
exit (1);
}
#endif
#if defined(BSD) && !defined(__APPLE__) && defined(USE_LIBSNDFILE)
int fmt;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev);
opts->audio_out = 0;
exit(1);
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf(stderr, "ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf(stderr, "ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf(stderr, "ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf(stderr, "ioctl setfmt error \n");
}
#endif
fprintf(stderr, "Audio Out Device: %s\n", opts->audio_out_dev);
}
void
openAudioInDevice (dsd_opts * opts)
{
#ifdef USE_LIBSNDFILE
// get info of device/file
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0) {
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev);
exit(1);
}
if(S_ISREG(stat_buf.st_mode)) { // is this a regular file? then process with libsndfile.
opts->audio_in_type = 1;
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->channels = 1;
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
if(opts->audio_in_file == NULL) {
fprintf(stderr, "Error, couldn't open file %s\n", opts->audio_in_dev);
exit(1); exit(1);
} }
}
else { // this is a device, use old handling
opts->audio_in_type = 0;
#ifdef SOLARIS #ifdef SOLARIS
sample_info_t aset, aget; sample_info_t aset, aget;
int rgain;
rgain = 64; opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
if (opts->split == 1) {
{ fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev);
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY); exit (1);
} }
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev);
exit(1);
}
// get current // get current
ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset); ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = 48000; aset.record.sample_rate = speed;
aset.play.sample_rate = 48000; aset.play.sample_rate = speed;
aset.record.channels = 1; aset.record.channels = 1;
aset.play.channels = 1; aset.play.channels = 1;
aset.record.precision = 16; aset.record.precision = 16;
aset.play.precision = 16; aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR; aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR; aset.play.encoding = AUDIO_ENCODING_LINEAR;
aset.record.port = AUDIO_LINE_IN;
aset.record.gain = rgain;
if (ioctl (opts->audio_in_fd, AUDIO_SETINFO, &aset) == -1) if (ioctl (opts->audio_out_fd, AUDIO_SETINFO, &aset) == -1)
{ {
fprintf(stderr, "Error setting sample device parameters\n"); fprintf(stderr, "Error setting sample device parameters\n");
exit (1); exit (1);
} }
#endif
#if defined(BSD) && !defined(__APPLE__) && defined(USE_LIBSNDFILE)
int fmt;
opts->audio_out_fd = open (opts->audio_out_dev, O_WRONLY);
if (opts->audio_out_fd == -1)
{
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev);
opts->audio_out = 0;
exit(1);
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_RESET) < 0)
{
fprintf(stderr, "ioctl reset error \n");
}
fmt = speed;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{
fprintf(stderr, "ioctl speed error \n");
}
fmt = 0;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{
fprintf(stderr, "ioctl stereo error \n");
}
fmt = AFMT_S16_LE;
if (ioctl (opts->audio_out_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{
fprintf(stderr, "ioctl setfmt error \n");
}
#endif
fprintf(stderr, "Audio Out Device: %s\n", opts->audio_out_dev);
}
void openAudioInDevice(dsd_opts * opts)
{
#ifdef USE_LIBSNDFILE
// get info of device/file
struct stat stat_buf;
if (stat(opts->audio_in_dev, &stat_buf) != 0)
{
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev);
exit(1);
}
if(S_ISREG(stat_buf.st_mode))
{ // is this a regular file? then process with libsndfile.
opts->audio_in_type = 1;
opts->audio_in_file_info = calloc(1, sizeof(SF_INFO));
opts->audio_in_file_info->channels = 1;
opts->audio_in_file = sf_open(opts->audio_in_dev, SFM_READ, opts->audio_in_file_info);
if(opts->audio_in_file == NULL)
{
fprintf(stderr, "Error, couldn't open file %s\n", opts->audio_in_dev);
exit(1);
}
}
else
{ // this is a device, use old handling
opts->audio_in_type = 0;
#ifdef SOLARIS
sample_info_t aset, aget;
int rgain;
rgain = 64;
if (opts->split == 1)
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
}
else
{
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
}
if (opts->audio_in_fd == -1)
{
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev);
exit(1);
}
// get current
ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset);
aset.record.sample_rate = 48000;
aset.play.sample_rate = 48000;
aset.record.channels = 1;
aset.play.channels = 1;
aset.record.precision = 16;
aset.play.precision = 16;
aset.record.encoding = AUDIO_ENCODING_LINEAR;
aset.play.encoding = AUDIO_ENCODING_LINEAR;
aset.record.port = AUDIO_LINE_IN;
aset.record.gain = rgain;
if (ioctl (opts->audio_in_fd, AUDIO_SETINFO, &aset) == -1)
{
fprintf(stderr, "Error setting sample device parameters\n");
exit (1);
}
#endif #endif
#if defined(BSD) && !defined(__APPLE__) #if defined(BSD) && !defined(__APPLE__)
int fmt; int fmt;
if (opts->split == 1) if (opts->split == 1)
{ {
opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY); opts->audio_in_fd = open (opts->audio_in_dev, O_RDONLY);
} }
else else
{ {
opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR); opts->audio_in_fd = open (opts->audio_in_dev, O_RDWR);
} }
if (opts->audio_in_fd == -1) if (opts->audio_in_fd == -1)
{ {
fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev); fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev);
opts->audio_out = 0; opts->audio_out = 0;
} }
fmt = 0; fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0) if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0)
{ {
fprintf(stderr, "ioctl reset error \n"); fprintf(stderr, "ioctl reset error \n");
} }
fmt = 48000; fmt = 48000;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0) if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0)
{ {
fprintf(stderr, "ioctl speed error \n"); fprintf(stderr, "ioctl speed error \n");
} }
fmt = 0; fmt = 0;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0) if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0)
{ {
fprintf(stderr, "ioctl stereo error \n"); fprintf(stderr, "ioctl stereo error \n");
} }
fmt = AFMT_S16_LE; fmt = AFMT_S16_LE;
if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0)
{ {
fprintf(stderr, "ioctl setfmt error \n"); fprintf(stderr, "ioctl setfmt error \n");
} }
#endif #endif
}
if (opts->split == 1)
{
fprintf(stderr, "Audio In Device: %s\n", opts->audio_in_dev);
} }
else if (opts->split == 1)
{ {
fprintf(stderr, "Audio In/Out Device: %s\n", opts->audio_in_dev); fprintf(stderr, "Audio In Device: %s\n", opts->audio_in_dev);
}
else
{
fprintf(stderr, "Audio In/Out Device: %s\n", opts->audio_in_dev);
} }
#endif #endif
} }

View File

@ -78,5 +78,6 @@ void initOpts(dsd_opts * opts)
opts->delay = 0; opts->delay = 0;
opts->use_cosine_filter = 1; opts->use_cosine_filter = 1;
opts->unmute_encrypted_p25 = 0; opts->unmute_encrypted_p25 = 0;
opts->upsample = 0; // by default stay with 8k audio
} }

View File

@ -132,5 +132,6 @@ void initState(dsd_state * state)
} }
state->dsd_running = 0; state->dsd_running = 0;
state->output_phasor = 0;
} }

View File

@ -111,9 +111,11 @@ typedef struct
short *output_buffer; //!< Output of decoder single S16LE short *output_buffer; //!< Output of decoder single S16LE
int output_offset; //!< producer pointer int output_offset; //!< producer pointer
short *output_samples; //!< L+R channels S16LE ready for writing to audio FIFO short *output_samples; //!< L+R channels S16LE ready for writing to audio FIFO
int output_buffers_size; //!< Size of buffers in number of samples
int output_num_samples; //!< Number of L+R samples available in the above buffer int output_num_samples; //!< Number of L+R samples available in the above buffer
int output_length; //!< L+R buffer size (fixed) int output_length; //!< Number of wished samples
int output_finished; //!< 0: not ready, 1: ready int output_finished; //!< 0: not ready, 1: ready
float output_phasor;
pthread_mutex_t input_mutex; pthread_mutex_t input_mutex;
pthread_cond_t input_ready; pthread_cond_t input_ready;

View File

@ -102,22 +102,36 @@ int getSymbol(dsd_opts * opts, dsd_state * state, int have_sync)
{ {
int i; int i;
state->input_length = 0; // states all samples have been consumed state->input_length = 0; // states all samples have been consumed
state->input_offset = 0;
// debug ...
for (i = 0; i < state->output_length; i++)
{
float s = sin(state->output_phasor);
state->output_phasor = fmod(state->output_phasor + (M_PI / 48.0), 2.0 * M_PI);
state->output_samples[2*state->output_offset + 2*i] = s * 16368.0f;
state->output_samples[2*state->output_offset + 2*i+1] = s * 16368.0f;
}
state->output_offset += state->output_length;
state->output_num_samples = state->output_offset; state->output_num_samples = state->output_offset;
// ... debug
//ffprintf(stderr, stderr, "dsd::getSymbol: input processing has finished\n"); // state->output_num_samples = state->output_offset;
//
if (state->output_num_samples > state->output_length) // //ffprintf(stderr, stderr, "dsd::getSymbol: input processing has finished\n");
{ //
fprintf(stderr, "WARNING: audio buffer over-run! Truncating output\n"); // if (state->output_num_samples > state->output_length)
state->output_num_samples = state->output_length; // {
} // fprintf(stderr, "WARNING: audio buffer over-run! Truncating output\n");
// state->output_num_samples = state->output_length;
for (i = 0; i < state->output_num_samples; i++) // }
{ //
state->output_samples[2*i] = state->output_buffer[i]; // L channel // for (i = 0; i < state->output_num_samples; i++)
state->output_samples[2*i+1] = state->output_buffer[i]; // R channel // {
} // state->output_samples[2*i] = state->output_buffer[i]; // L channel
// state->output_samples[2*i+1] = state->output_buffer[i]; // R channel
// }
//
state->output_finished = 1; state->output_finished = 1;
} }
else else

View File

@ -17,52 +17,100 @@
#include "dsd.h" #include "dsd.h"
void void upsample(dsd_state * state, float invalue)
upsample (dsd_state * state, float invalue)
{ {
int i, j, sum; int i, j, sum;
float *outbuf1, c, d; float *outbuf1, c, d;
outbuf1 = state->audio_out_float_buf_p; outbuf1 = state->audio_out_float_buf_p;
outbuf1--; outbuf1--;
c = *outbuf1; c = *outbuf1;
d = invalue; d = invalue;
// basic triangle interpolation // basic triangle interpolation
outbuf1++; outbuf1++;
*outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834)); *outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834));
outbuf1++; outbuf1++;
*outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668)); *outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668));
outbuf1++; outbuf1++;
*outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5)); *outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5));
outbuf1++; outbuf1++;
*outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332)); *outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332));
outbuf1++; outbuf1++;
*outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166)); *outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166));
outbuf1++; outbuf1++;
*outbuf1 = d; *outbuf1 = d;
outbuf1++; outbuf1++;
if (state->audio_out_idx2 > 24) if (state->audio_out_idx2 > 24)
{ {
// smoothing // smoothing
outbuf1 -= 16; outbuf1 -= 16;
for (j = 0; j < 4; j++) for (j = 0; j < 4; j++)
{ {
for (i = 0; i < 6; i++) for (i = 0; i < 6; i++)
{ {
sum = 0; sum = 0;
outbuf1 -= 2; outbuf1 -= 2;
sum += *outbuf1; sum += *outbuf1;
outbuf1 += 2; outbuf1 += 2;
sum += *outbuf1; sum += *outbuf1;
outbuf1 += 2; outbuf1 += 2;
sum += *outbuf1; sum += *outbuf1;
outbuf1 -= 2; outbuf1 -= 2;
*outbuf1 = (sum / (float) 3); *outbuf1 = (sum / (float) 3);
outbuf1++; outbuf1++;
} }
outbuf1 -= 8; outbuf1 -= 8;
}
}
}
void upsample16(dsd_state * state, short invalue)
{
int i, j, sum;
float *outbuf1, c, d;
outbuf1 = state->audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
d = invalue;
// basic triangle interpolation
outbuf1++;
*outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166));
outbuf1++;
*outbuf1 = d;
outbuf1++;
if (state->audio_out_idx2 > 24)
{
// smoothing
outbuf1 -= 16;
for (j = 0; j < 4; j++)
{
for (i = 0; i < 6; i++)
{
sum = 0;
outbuf1 -= 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 -= 2;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 8;
} }
} }
} }

View File

@ -18,6 +18,8 @@
#include <QtGlobal> #include <QtGlobal>
#include "dsddecoder.h" #include "dsddecoder.h"
#include "dsd_livescanner.h" #include "dsd_livescanner.h"
#include "audio/audiofifo.h"
DSDDecoder::DSDDecoder() DSDDecoder::DSDDecoder()
{ {
@ -25,6 +27,7 @@ DSDDecoder::DSDDecoder()
initState(&m_dsdParams.state); initState(&m_dsdParams.state);
m_dsdParams.opts.split = 1; m_dsdParams.opts.split = 1;
m_dsdParams.opts.upsample = 1; // force upsampling of audio to 48k
m_dsdParams.opts.playoffset = 0; m_dsdParams.opts.playoffset = 0;
m_dsdParams.opts.delay = 0; m_dsdParams.opts.delay = 0;
m_dsdParams.opts.audio_in_type = 0; m_dsdParams.opts.audio_in_type = 0;
@ -54,6 +57,7 @@ DSDDecoder::DSDDecoder()
m_dsdParams.state.output_buffer = (short *) malloc(1<<18); // Raw output buffer with single S16LE samples @ 8k (max: 128 kS) m_dsdParams.state.output_buffer = (short *) malloc(1<<18); // Raw output buffer with single S16LE samples @ 8k (max: 128 kS)
m_dsdParams.state.output_offset = 0; m_dsdParams.state.output_offset = 0;
m_dsdParams.state.output_finished = 0;
if (m_dsdParams.state.output_buffer == NULL) if (m_dsdParams.state.output_buffer == NULL)
{ {
@ -61,13 +65,17 @@ DSDDecoder::DSDDecoder()
} }
m_dsdParams.state.output_samples = (short *) malloc(1<<19); // Audio output buffer with L+R S16LE samples (max: 128 kS) m_dsdParams.state.output_samples = (short *) malloc(1<<19); // Audio output buffer with L+R S16LE samples (max: 128 kS)
m_dsdParams.state.output_length = 1<<19; // the buffer size fixed m_dsdParams.state.output_buffers_size = 1<<17; // the buffers size in number of samples: 128 kS
if (m_dsdParams.state.output_samples == NULL) if (m_dsdParams.state.output_samples == NULL)
{ {
qCritical("DSDDecoder::DSDDecoder: Unable to allocate audio L+R buffer."); qCritical("DSDDecoder::DSDDecoder: Unable to allocate audio L+R buffer.");
} }
m_dsdParams.state.output_offset = 0;
m_zeroBuffer = new short[1<<18]; // 128 kS
memset(m_zeroBuffer, 0, sizeof(short) * (1<<18));
m_lastNbSamples = 0;
} }
DSDDecoder::~DSDDecoder() DSDDecoder::~DSDDecoder()
@ -83,12 +91,45 @@ void DSDDecoder::setInBuffer(const short *inBuffer)
void DSDDecoder::pushSamples(int nbSamples) void DSDDecoder::pushSamples(int nbSamples)
{ {
m_dsdParams.state.input_offset = 0; if (nbSamples == 0)
m_dsdParams.state.input_length = nbSamples; {
m_lastNbSamples = 0;
if (pthread_cond_signal(&m_dsdParams.state.input_ready)) { m_dsdParams.state.output_offset = 0; // reset output
printf("DSDDecoder::pushSamples: Unable to signal input ready");
} }
else
{
m_dsdParams.state.input_offset = 0;
m_dsdParams.state.input_length = nbSamples;
m_dsdParams.state.output_finished = 0;
m_dsdParams.state.output_length = m_lastNbSamples;
m_lastNbSamples = nbSamples;
if (pthread_cond_signal(&m_dsdParams.state.input_ready)) {
printf("DSDDecoder::pushSamples: Unable to signal input ready");
}
}
}
void DSDDecoder::popAudioSamples(AudioFifo *audioFifo, bool audioMute)
{
if (audioMute)
{
uint res = audioFifo->write((const quint8*) m_zeroBuffer, m_dsdParams.state.output_num_samples, 10);
if (res != m_dsdParams.state.output_num_samples) {
qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_dsdParams.state.output_num_samples);
}
}
else if (m_dsdParams.state.output_finished)
{
uint res = audioFifo->write((const quint8*) m_dsdParams.state.output_samples, m_dsdParams.state.output_num_samples, 10);
if (res != m_dsdParams.state.output_num_samples) {
qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_dsdParams.state.output_num_samples);
}
}
m_dsdParams.state.output_finished = 0; // will be done by the next push anyway
} }
void DSDDecoder::start() void DSDDecoder::start()
@ -102,6 +143,8 @@ void DSDDecoder::start()
m_dsdParams.state.dsd_running = 0; m_dsdParams.state.dsd_running = 0;
} }
m_lastNbSamples = 0;
qDebug("DSDDecoder::start: started"); qDebug("DSDDecoder::start: started");
} }

View File

@ -20,6 +20,8 @@
#include "dsd.h" #include "dsd.h"
class AudioFifo;
class DSDDecoder class DSDDecoder
{ {
public: public:
@ -27,7 +29,9 @@ public:
~DSDDecoder(); ~DSDDecoder();
void setInBuffer(const short *inBuffer); void setInBuffer(const short *inBuffer);
void pushSample(short sample);
void pushSamples(int nbSamples); // Push this amount of samples to the DSD decoder thread void pushSamples(int nbSamples); // Push this amount of samples to the DSD decoder thread
void popAudioSamples(AudioFifo *audioFifo, bool audioMute);
void start(); void start();
void stop(); void stop();
@ -42,6 +46,8 @@ private:
static void* run_dsd(void *arg); static void* run_dsd(void *arg);
dsd_params m_dsdParams; dsd_params m_dsdParams;
short *m_zeroBuffer;
int m_lastNbSamples;
}; };
#endif /* PLUGINS_CHANNEL_DEMODDSD_DSDDECODER_H_ */ #endif /* PLUGINS_CHANNEL_DEMODDSD_DSDDECODER_H_ */

View File

@ -145,52 +145,51 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto
m_scopeSampleBuffer.push_back(s); m_scopeSampleBuffer.push_back(s);
m_dsdInBuffer[m_dsdInCount++] = sample; m_dsdInBuffer[m_dsdInCount++] = sample;
if (m_running.m_audioMute) // if (m_running.m_audioMute)
{ // {
m_audioBuffer[m_audioBufferFill].l = 0; // m_audioBuffer[m_audioBufferFill].l = 0;
m_audioBuffer[m_audioBufferFill].r = 0; // m_audioBuffer[m_audioBufferFill].r = 0;
} // }
else // else
{ // {
m_audioBuffer[m_audioBufferFill].l = sample; // m_audioBuffer[m_audioBufferFill].l = sample;
m_audioBuffer[m_audioBufferFill].r = sample; // m_audioBuffer[m_audioBufferFill].r = sample;
} // }
//
++m_audioBufferFill; // ++m_audioBufferFill;
//
if (m_audioBufferFill >= m_audioBuffer.size()) // if (m_audioBufferFill >= m_audioBuffer.size())
{ // {
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); // uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10);
//
if (res != m_audioBufferFill) // if (res != m_audioBufferFill)
{ // {
qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); // qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_audioBufferFill);
} // }
//
m_audioBufferFill = 0; // m_audioBufferFill = 0;
} // }
m_interpolatorDistanceRemain += m_interpolatorDistance; m_interpolatorDistanceRemain += m_interpolatorDistance;
} }
} }
} }
if (m_audioBufferFill > 0)
{
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10);
if (res != m_audioBufferFill) // if (m_audioBufferFill > 0)
{ // {
qDebug("NFMDemod::feed: %u/%u tail samples written", res, m_audioBufferFill); // uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10);
} //
// if (res != m_audioBufferFill)
// {
// qDebug("NFMDemod::feed: %u/%u tail samples written", res, m_audioBufferFill);
// }
//
// m_audioBufferFill = 0;
// }
m_audioBufferFill = 0; m_dsdDecoder.popAudioSamples(&m_audioFifo, m_running.m_audioMute);
} m_dsdDecoder.pushSamples(m_dsdInCount);
if (m_dsdInCount > 0)
{
m_dsdDecoder.pushSamples(m_dsdInCount);
}
if((m_scope != 0) && (m_scopeEnabled)) if((m_scope != 0) && (m_scopeEnabled))
{ {

View File

@ -179,7 +179,7 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen)
if (samples != framesPerBuffer) if (samples != framesPerBuffer)
{ {
qDebug("AudioOutput::readData: read %d samples vs %d requested", samples, framesPerBuffer); //qDebug("AudioOutput::readData: read %d samples vs %d requested", samples, framesPerBuffer);
} }
for (uint i = 0; i < samples; i++) for (uint i = 0; i < samples; i++)