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:
parent
9ef7497c40
commit
5872ee0ca7
619
dsd/dsd_audio.c
619
dsd/dsd_audio.c
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,5 +132,6 @@ void initState(dsd_state * state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
state->dsd_running = 0;
|
state->dsd_running = 0;
|
||||||
|
state->output_phasor = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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_ */
|
||||||
|
@ -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))
|
||||||
{
|
{
|
||||||
|
@ -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++)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user