From 5872ee0ca704b77bc2492638110670c8ddfa4e5e Mon Sep 17 00:00:00 2001 From: f4exb Date: Sat, 9 Apr 2016 13:12:48 +0200 Subject: [PATCH] DSD demod plugin: DSD proper integration interim state #1 --- dsd/dsd_audio.c | 619 ++++++++++++------------ dsd/dsd_opts.c | 1 + dsd/dsd_state.c | 1 + dsd/dsd_state.h | 4 +- dsd/dsd_symbol.c | 42 +- dsd/dsd_upsample.c | 124 +++-- plugins/channel/demoddsd/dsddecoder.cpp | 55 ++- plugins/channel/demoddsd/dsddecoder.h | 6 + plugins/channel/demoddsd/dsddemod.cpp | 75 ++- sdrbase/audio/audiooutput.cpp | 2 +- 10 files changed, 526 insertions(+), 403 deletions(-) diff --git a/dsd/dsd_audio.c b/dsd/dsd_audio.c index 8c15948b3..75f109ad7 100644 --- a/dsd/dsd_audio.c +++ b/dsd/dsd_audio.c @@ -17,424 +17,433 @@ #include "dsd.h" -void -processAudio (dsd_opts * opts, dsd_state * state) +void processAudio(dsd_opts * opts, dsd_state * state) { - int i, n; - float aout_abs, max, gainfactor, gaindelta, maxbuf; + int i, n; + float aout_abs, max, gainfactor, gaindelta, maxbuf; - if (opts->audio_gain == (float) 0) + if (opts->audio_gain == (float) 0) { - // detect max level - max = 0; - state->audio_out_temp_buf_p = state->audio_out_temp_buf; - for (n = 0; n < 160; n++) + // detect max level + max = 0; + state->audio_out_temp_buf_p = state->audio_out_temp_buf; + for (n = 0; n < 160; n++) { - aout_abs = fabsf (*state->audio_out_temp_buf_p); - if (aout_abs > max) + aout_abs = fabsf(*state->audio_out_temp_buf_p); + 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++; - state->aout_max_buf_idx++; - if (state->aout_max_buf_idx > 24) + *state->aout_max_buf_p = max; + state->aout_max_buf_p++; + state->aout_max_buf_idx++; + if (state->aout_max_buf_idx > 24) { - state->aout_max_buf_idx = 0; - state->aout_max_buf_p = state->aout_max_buf; + state->aout_max_buf_idx = 0; + state->aout_max_buf_p = state->aout_max_buf; } - // lookup max history - for (i = 0; i < 25; i++) + // lookup max history + for (i = 0; i < 25; i++) { - maxbuf = state->aout_max_buf[i]; - if (maxbuf > max) + maxbuf = state->aout_max_buf[i]; + if (maxbuf > max) { - max = maxbuf; + max = maxbuf; } } - // determine optimal gain level - if (max > (float) 0) + // determine optimal gain level + 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; - gaindelta = (float) 0; + state->aout_gain = gainfactor; + gaindelta = (float) 0; } - else + else { - if (gainfactor > (float) 50) + if (gainfactor > (float) 50) { - gainfactor = (float) 50; + gainfactor = (float) 50; } - gaindelta = gainfactor - state->aout_gain; - if (gaindelta > ((float) 0.05 * state->aout_gain)) + gaindelta = gainfactor - 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){ - // adjust output gain + if (opts->audio_gain >= 0) + { + // 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; - 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; - if (opts->split == 0) + if ((opts->split == 0) || (opts->upsample)) { - for (n = 0; n < 160; n++) + for (n = 0; n < 160; n++) { - upsample (state, *state->audio_out_temp_buf_p); - state->audio_out_temp_buf_p++; - state->audio_out_float_buf_p += 6; - state->audio_out_idx += 6; - state->audio_out_idx2 += 6; + upsample(state, *state->audio_out_temp_buf_p); + state->audio_out_temp_buf_p++; + state->audio_out_float_buf_p += 6; + state->audio_out_idx += 6; + state->audio_out_idx2 += 6; } - state->audio_out_float_buf_p -= (960 + opts->playoffset); - // copy to output (short) buffer - for (n = 0; n < 960; n++) + state->audio_out_float_buf_p -= (960 + opts->playoffset); + // copy to output (short) buffer + 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++; - 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_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++; - state->audio_out_temp_buf_p++; - state->audio_out_idx++; - state->audio_out_idx2++; + *state->audio_out_buf_p = (short) *state->audio_out_temp_buf_p; + state->audio_out_buf_p++; + state->audio_out_temp_buf_p++; + state->audio_out_idx++; + state->audio_out_idx2++; } } } -void -writeSynthesizedVoice (dsd_opts * opts, dsd_state * state) +void writeSynthesizedVoice(dsd_opts * opts, dsd_state * state) { #ifdef USE_LIBSNDFILE - int n; - short aout_buf[160]; - short *aout_buf_p; + int n; + short aout_buf[160]; + short *aout_buf_p; // for(n=0; n<160; n++) // fprintf(stderr, "%d ", ((short*)(state->audio_out_temp_buf))[n]); // fprintf(stderr, "\n"); - aout_buf_p = aout_buf; - state->audio_out_temp_buf_p = state->audio_out_temp_buf; + 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) 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++) + 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++; - state->audio_out_temp_buf_p++; + *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; - */ + 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) + { + *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 } -void -playSynthesizedVoice (dsd_opts * opts, dsd_state * state) +void 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 - if (opts->audio_out_fd == -1) + // output synthesized speech to sound card + 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)); - state->output_offset += state->audio_out_idx; + memcpy(state->output_buffer + state->output_offset, + (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_buf_p = state->audio_out_buf + 100; - memset (state->audio_out_float_buf, 0, 100 * sizeof (float)); - memset (state->audio_out_buf, 0, 100 * sizeof (short)); - state->audio_out_idx2 = 0; + state->audio_out_float_buf_p = state->audio_out_float_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_buf, 0, 100 * sizeof(short)); + state->audio_out_idx2 = 0; } } -void -openAudioOutDevice (dsd_opts * opts, int speed) +void openAudioOutDevice(dsd_opts * opts, int speed) { - // get info of device/file - struct stat stat_buf; - 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) + // get info of device/file + struct stat stat_buf; + if (stat(opts->audio_out_dev, &stat_buf) != 0) { - fprintf(stderr, "Error, couldn't open %s\n", opts->audio_out_dev); - exit (1); - } - - // get current - ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset); - - aset.record.sample_rate = speed; - aset.play.sample_rate = speed; - 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); + 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); } - } - 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); - } + 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); + exit (1); + } // get current - ioctl (opts->audio_in_fd, AUDIO_GETINFO, &aset); + ioctl (opts->audio_out_fd, AUDIO_GETINFO, &aset); - aset.record.sample_rate = 48000; - aset.play.sample_rate = 48000; + aset.record.sample_rate = speed; + aset.play.sample_rate = speed; 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) - { + 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); + } + } + 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 #if defined(BSD) && !defined(__APPLE__) - int fmt; + int fmt; - 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->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); - opts->audio_out = 0; - } + if (opts->audio_in_fd == -1) + { + fprintf(stderr, "Error, couldn't open %s\n", opts->audio_in_dev); + opts->audio_out = 0; + } - fmt = 0; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0) - { - fprintf(stderr, "ioctl reset error \n"); - } - fmt = 48000; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0) - { - fprintf(stderr, "ioctl speed error \n"); - } - fmt = 0; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0) - { - fprintf(stderr, "ioctl stereo error \n"); - } - fmt = AFMT_S16_LE; - if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) - { - fprintf(stderr, "ioctl setfmt error \n"); - } + fmt = 0; + if (ioctl (opts->audio_in_fd, SNDCTL_DSP_RESET) < 0) + { + fprintf(stderr, "ioctl reset error \n"); + } + fmt = 48000; + if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SPEED, &fmt) < 0) + { + fprintf(stderr, "ioctl speed error \n"); + } + fmt = 0; + if (ioctl (opts->audio_in_fd, SNDCTL_DSP_STEREO, &fmt) < 0) + { + fprintf(stderr, "ioctl stereo error \n"); + } + fmt = AFMT_S16_LE; + if (ioctl (opts->audio_in_fd, SNDCTL_DSP_SETFMT, &fmt) < 0) + { + fprintf(stderr, "ioctl setfmt error \n"); + } #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 } diff --git a/dsd/dsd_opts.c b/dsd/dsd_opts.c index 5cecf3926..1aae0c905 100644 --- a/dsd/dsd_opts.c +++ b/dsd/dsd_opts.c @@ -78,5 +78,6 @@ void initOpts(dsd_opts * opts) opts->delay = 0; opts->use_cosine_filter = 1; opts->unmute_encrypted_p25 = 0; + opts->upsample = 0; // by default stay with 8k audio } diff --git a/dsd/dsd_state.c b/dsd/dsd_state.c index 236c29fd8..48dc08a61 100644 --- a/dsd/dsd_state.c +++ b/dsd/dsd_state.c @@ -132,5 +132,6 @@ void initState(dsd_state * state) } state->dsd_running = 0; + state->output_phasor = 0; } diff --git a/dsd/dsd_state.h b/dsd/dsd_state.h index 75b94a909..e64f71274 100644 --- a/dsd/dsd_state.h +++ b/dsd/dsd_state.h @@ -111,9 +111,11 @@ typedef struct short *output_buffer; //!< Output of decoder single S16LE int output_offset; //!< producer pointer 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_length; //!< L+R buffer size (fixed) + int output_length; //!< Number of wished samples int output_finished; //!< 0: not ready, 1: ready + float output_phasor; pthread_mutex_t input_mutex; pthread_cond_t input_ready; diff --git a/dsd/dsd_symbol.c b/dsd/dsd_symbol.c index 2bdbda3e6..da68809bb 100644 --- a/dsd/dsd_symbol.c +++ b/dsd/dsd_symbol.c @@ -102,22 +102,36 @@ int getSymbol(dsd_opts * opts, dsd_state * state, int have_sync) { int i; 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; + // ... debug - //ffprintf(stderr, stderr, "dsd::getSymbol: input processing has finished\n"); - - if (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 - state->output_samples[2*i+1] = state->output_buffer[i]; // R channel - } - +// state->output_num_samples = state->output_offset; +// +// //ffprintf(stderr, stderr, "dsd::getSymbol: input processing has finished\n"); +// +// if (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 +// state->output_samples[2*i+1] = state->output_buffer[i]; // R channel +// } +// state->output_finished = 1; } else diff --git a/dsd/dsd_upsample.c b/dsd/dsd_upsample.c index 3bbc584df..8caa157db 100644 --- a/dsd/dsd_upsample.c +++ b/dsd/dsd_upsample.c @@ -17,52 +17,100 @@ #include "dsd.h" -void -upsample (dsd_state * state, float invalue) +void upsample(dsd_state * state, float invalue) { - int i, j, sum; - float *outbuf1, c, d; + 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++; + 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) + if (state->audio_out_idx2 > 24) { - // smoothing - outbuf1 -= 16; - for (j = 0; j < 4; j++) + // smoothing + outbuf1 -= 16; + for (j = 0; j < 4; j++) { - for (i = 0; i < 6; i++) + 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++; + sum = 0; + outbuf1 -= 2; + sum += *outbuf1; + outbuf1 += 2; + sum += *outbuf1; + outbuf1 += 2; + sum += *outbuf1; + outbuf1 -= 2; + *outbuf1 = (sum / (float) 3); + 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; } } } diff --git a/plugins/channel/demoddsd/dsddecoder.cpp b/plugins/channel/demoddsd/dsddecoder.cpp index 1d1d0e206..fd7ff2429 100644 --- a/plugins/channel/demoddsd/dsddecoder.cpp +++ b/plugins/channel/demoddsd/dsddecoder.cpp @@ -18,6 +18,8 @@ #include #include "dsddecoder.h" #include "dsd_livescanner.h" +#include "audio/audiofifo.h" + DSDDecoder::DSDDecoder() { @@ -25,6 +27,7 @@ DSDDecoder::DSDDecoder() initState(&m_dsdParams.state); m_dsdParams.opts.split = 1; + m_dsdParams.opts.upsample = 1; // force upsampling of audio to 48k m_dsdParams.opts.playoffset = 0; m_dsdParams.opts.delay = 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_offset = 0; + m_dsdParams.state.output_finished = 0; 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_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) { 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() @@ -83,12 +91,45 @@ void DSDDecoder::setInBuffer(const short *inBuffer) void DSDDecoder::pushSamples(int nbSamples) { - m_dsdParams.state.input_offset = 0; - m_dsdParams.state.input_length = nbSamples; - - if (pthread_cond_signal(&m_dsdParams.state.input_ready)) { - printf("DSDDecoder::pushSamples: Unable to signal input ready"); + if (nbSamples == 0) + { + m_lastNbSamples = 0; + m_dsdParams.state.output_offset = 0; // reset output } + 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() @@ -102,6 +143,8 @@ void DSDDecoder::start() m_dsdParams.state.dsd_running = 0; } + m_lastNbSamples = 0; + qDebug("DSDDecoder::start: started"); } diff --git a/plugins/channel/demoddsd/dsddecoder.h b/plugins/channel/demoddsd/dsddecoder.h index dd55fb826..5e47e938a 100644 --- a/plugins/channel/demoddsd/dsddecoder.h +++ b/plugins/channel/demoddsd/dsddecoder.h @@ -20,6 +20,8 @@ #include "dsd.h" +class AudioFifo; + class DSDDecoder { public: @@ -27,7 +29,9 @@ public: ~DSDDecoder(); void setInBuffer(const short *inBuffer); + void pushSample(short sample); void pushSamples(int nbSamples); // Push this amount of samples to the DSD decoder thread + void popAudioSamples(AudioFifo *audioFifo, bool audioMute); void start(); void stop(); @@ -42,6 +46,8 @@ private: static void* run_dsd(void *arg); dsd_params m_dsdParams; + short *m_zeroBuffer; + int m_lastNbSamples; }; #endif /* PLUGINS_CHANNEL_DEMODDSD_DSDDECODER_H_ */ diff --git a/plugins/channel/demoddsd/dsddemod.cpp b/plugins/channel/demoddsd/dsddemod.cpp index 99c6be73b..0474eb7ed 100644 --- a/plugins/channel/demoddsd/dsddemod.cpp +++ b/plugins/channel/demoddsd/dsddemod.cpp @@ -145,52 +145,51 @@ void DSDDemod::feed(const SampleVector::const_iterator& begin, const SampleVecto m_scopeSampleBuffer.push_back(s); m_dsdInBuffer[m_dsdInCount++] = sample; - if (m_running.m_audioMute) - { - m_audioBuffer[m_audioBufferFill].l = 0; - m_audioBuffer[m_audioBufferFill].r = 0; - } - else - { - m_audioBuffer[m_audioBufferFill].l = sample; - m_audioBuffer[m_audioBufferFill].r = sample; - } - - ++m_audioBufferFill; - - if (m_audioBufferFill >= m_audioBuffer.size()) - { - uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); - - if (res != m_audioBufferFill) - { - qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); - } - - m_audioBufferFill = 0; - } +// if (m_running.m_audioMute) +// { +// m_audioBuffer[m_audioBufferFill].l = 0; +// m_audioBuffer[m_audioBufferFill].r = 0; +// } +// else +// { +// m_audioBuffer[m_audioBufferFill].l = sample; +// m_audioBuffer[m_audioBufferFill].r = sample; +// } +// +// ++m_audioBufferFill; +// +// if (m_audioBufferFill >= m_audioBuffer.size()) +// { +// uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); +// +// if (res != m_audioBufferFill) +// { +// qDebug("DSDDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); +// } +// +// m_audioBufferFill = 0; +// } 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) - { - qDebug("NFMDemod::feed: %u/%u tail samples written", res, m_audioBufferFill); - } +// if (m_audioBufferFill > 0) +// { +// 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; - } - - if (m_dsdInCount > 0) - { - m_dsdDecoder.pushSamples(m_dsdInCount); - } + m_dsdDecoder.popAudioSamples(&m_audioFifo, m_running.m_audioMute); + m_dsdDecoder.pushSamples(m_dsdInCount); if((m_scope != 0) && (m_scopeEnabled)) { diff --git a/sdrbase/audio/audiooutput.cpp b/sdrbase/audio/audiooutput.cpp index 3deb9ba82..c4a0c06ef 100644 --- a/sdrbase/audio/audiooutput.cpp +++ b/sdrbase/audio/audiooutput.cpp @@ -179,7 +179,7 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen) 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++)