Correcting all levels and move all remaining integer samples to sample_t
The leves are based on the standards of each mobile network. They are adjusted to the specified frequency deviation now.
This commit is contained in:
@@ -35,6 +35,23 @@
|
||||
|
||||
#define DISC_TIMEOUT 30
|
||||
|
||||
//#define DEBUG_LEVEL
|
||||
|
||||
#ifdef DEBUG_LEVEL
|
||||
static double level_of(double *samples, int count)
|
||||
{
|
||||
double level = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
if (samples[i] > level)
|
||||
level = samples[i];
|
||||
}
|
||||
|
||||
return level;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* stream patterns/announcements */
|
||||
int16_t *test_spl = NULL;
|
||||
int16_t *ringback_spl = NULL;
|
||||
@@ -221,7 +238,7 @@ static void get_test_patterns(int16_t *samples, int length)
|
||||
if (pos >= size)
|
||||
*samples++ = 0;
|
||||
else
|
||||
*samples++ = spl[pos] >> 1;
|
||||
*samples++ = spl[pos] >> 2;
|
||||
if (++pos == max)
|
||||
pos = 0;
|
||||
}
|
||||
@@ -477,7 +494,8 @@ int call_init(const char *station_id, const char *audiodev, int samplerate, int
|
||||
return 0;
|
||||
|
||||
/* open sound device for call control */
|
||||
call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 3700.0, 0.0);
|
||||
/* use +3.17 dBm0 (factor 1.44) for complete range of sound card */
|
||||
call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 1.44, 4000.0);
|
||||
if (!call.sound) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n");
|
||||
|
||||
@@ -677,7 +695,6 @@ void process_call(int c)
|
||||
default:
|
||||
jitter_load(&call.dejitter, samples, count);
|
||||
}
|
||||
samples_to_int16(spl, samples, count);
|
||||
samples_list[0] = samples;
|
||||
rc = sound_write(call.sound, samples_list, count, NULL, NULL, 1);
|
||||
if (rc < 0) {
|
||||
@@ -904,8 +921,6 @@ void call_in_release(int callref, int cause)
|
||||
/* forward audio to MNCC or call instance */
|
||||
void call_tx_audio(int callref, sample_t *samples, int count)
|
||||
{
|
||||
int16_t spl[count];
|
||||
|
||||
if (!callref)
|
||||
return;
|
||||
|
||||
@@ -920,6 +935,10 @@ void call_tx_audio(int callref, sample_t *samples, int count)
|
||||
/* forward audio */
|
||||
data->msg_type = ANALOG_8000HZ;
|
||||
data->callref = callref;
|
||||
#ifdef DEBUG_LEVEL
|
||||
double lev = level_of(samples, count);
|
||||
printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||
#endif
|
||||
samples_to_int16((int16_t *)data->data, samples, count);
|
||||
|
||||
mncc_write(buf, sizeof(buf));
|
||||
@@ -934,6 +953,7 @@ void call_tx_audio(int callref, sample_t *samples, int count)
|
||||
} else
|
||||
/* else, if no sound is used, send test tone to mobile */
|
||||
if (call.state == CALL_CONNECT) {
|
||||
int16_t spl[count];
|
||||
get_test_patterns(spl, count);
|
||||
int16_to_samples(samples, spl, count);
|
||||
call_rx_audio(callref, samples, count);
|
||||
@@ -953,6 +973,13 @@ void call_mncc_clock(void)
|
||||
data->callref = process->callref;
|
||||
/* try to get patterns, else copy the samples we got */
|
||||
get_process_patterns(process, (int16_t *)data->data, 160);
|
||||
#ifdef DEBUG_LEVEL
|
||||
sample_t samples[160];
|
||||
int16_to_samples(samples, (int16_t *)data->data, 160);
|
||||
double lev = level_of(samples, 160);
|
||||
printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||
samples_to_int16((int16_t *)data->data, samples, 160);
|
||||
#endif
|
||||
mncc_write(buf, sizeof(buf));
|
||||
}
|
||||
process = process->next;
|
||||
@@ -978,6 +1005,10 @@ void call_mncc_recv(uint8_t *buf, int length)
|
||||
if (is_process_pattern(data->callref))
|
||||
return;
|
||||
int16_to_samples(samples, (int16_t *)data->data, count);
|
||||
#ifdef DEBUG_LEVEL
|
||||
double lev = level_of(samples, count);
|
||||
printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev)));
|
||||
#endif
|
||||
call_rx_audio(data->callref, samples, count);
|
||||
return;
|
||||
}
|
||||
|
@@ -35,6 +35,9 @@
|
||||
/* Minimum level value to keep state */
|
||||
#define ENVELOPE_MIN 0.001
|
||||
|
||||
/* Maximum level, to prevent sqrt_tab to overflow */
|
||||
#define ENVELOPE_MAX 9.990
|
||||
|
||||
static double sqrt_tab[10000];
|
||||
|
||||
/*
|
||||
@@ -43,7 +46,7 @@ static double sqrt_tab[10000];
|
||||
* Hopefully this is correct
|
||||
*
|
||||
*/
|
||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level)
|
||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -95,6 +98,8 @@ void compress_audio(compandor_t *state, sample_t *samples, int num)
|
||||
envelope = peak;
|
||||
if (envelope < ENVELOPE_MIN)
|
||||
envelope = ENVELOPE_MIN;
|
||||
if (envelope > ENVELOPE_MAX)
|
||||
envelope = ENVELOPE_MAX;
|
||||
|
||||
value = value / sqrt_tab[(int)(envelope / 0.001)];
|
||||
//if (i > 47000.0 && i < 48144)
|
||||
|
@@ -15,7 +15,7 @@ typedef struct compandor {
|
||||
} e;
|
||||
} compandor_t;
|
||||
|
||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level);
|
||||
void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level);
|
||||
void compress_audio(compandor_t *state, sample_t *samples, int num);
|
||||
void expand_audio(compandor_t *state, sample_t *samples, int num);
|
||||
|
||||
|
@@ -23,7 +23,7 @@ void get_win_size(int *w, int *h);
|
||||
void display_wave_init(sender_t *sender, int samplerate);
|
||||
void display_wave_on(int on);
|
||||
void display_wave_limit_scroll(int on);
|
||||
void display_wave(sender_t *sender, sample_t *samples, int length);
|
||||
void display_wave(sender_t *sender, sample_t *samples, int length, double range);
|
||||
|
||||
void display_iq_init(int samplerate);
|
||||
void display_iq_on(int on);
|
||||
|
@@ -20,6 +20,7 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include "sample.h"
|
||||
#include "sender.h"
|
||||
@@ -110,10 +111,10 @@ void display_wave_limit_scroll(int on)
|
||||
* HEIGHT is odd, so the center line's char is '-' (otherwise '_')
|
||||
* (HEIGHT - 1) / 2 = 1, so the center line is drawn in line 1
|
||||
*
|
||||
* y is in range of 0..5, so these are 5 steps, where 2 to 2.999 is the
|
||||
* y is in range of 0..4, so these are 5 steps, where 2 is the
|
||||
* center line. this is calculated by (HEIGHT * 2 - 1)
|
||||
*/
|
||||
void display_wave(sender_t *sender, sample_t *samples, int length)
|
||||
void display_wave(sender_t *sender, sample_t *samples, int length, double range)
|
||||
{
|
||||
dispwav_t *disp = &sender->dispwav;
|
||||
int pos, max;
|
||||
@@ -147,9 +148,16 @@ void display_wave(sender_t *sender, sample_t *samples, int length)
|
||||
if (pos == width) {
|
||||
memset(&screen, ' ', sizeof(screen));
|
||||
for (j = 0; j < width; j++) {
|
||||
y = (32767 - (int32_t)buffer[j]) * (HEIGHT * 2 - 1) / 65536;
|
||||
/* Input value is scaled to range -1 .. 1 and then substracted from 1,
|
||||
* so the result ranges from 0 .. 2.
|
||||
* HEIGHT-1 is multiplied with the range, so a HEIGHT of 3 would allow
|
||||
* 0..4 (5 steps) and a HEIGHT of 11 would allow 0..20 (21 steps).
|
||||
* We always use odd number of steps, so there will be a center between
|
||||
* values.
|
||||
*/
|
||||
y = round((1.0 - buffer[j] / range) * (double)(HEIGHT - 1));
|
||||
/* only display level, if it is in range */
|
||||
if (y >= 0 && y < HEIGHT * 2)
|
||||
if (y >= 0 && y < HEIGHT * 2 - 1)
|
||||
screen[y >> 1][j] = (y & 1) ? '_' : '-';
|
||||
}
|
||||
sprintf(screen[0], "(chan %d", sender->kanal);
|
||||
|
@@ -25,10 +25,12 @@
|
||||
|
||||
#define PI M_PI
|
||||
|
||||
#define TX_PEAK_DTMF 7000 /* single dtmf tone peak (note this is half to total peak) */
|
||||
#define DTMF_DURATION 0.100 /* duration in seconds */
|
||||
static double tx_peak_dtmf_low = 0.2818 / SPEECH_LEVEL; /* -11 dBm, relative to speech level */
|
||||
static double tx_peak_dtmf_high = 0.3548 / SPEECH_LEVEL;/* -9 dBm, relative to speech level */
|
||||
#define DTMF_DURATION 0.100 /* duration in seconds */
|
||||
|
||||
static double dsp_sine_dtmf[256];
|
||||
static sample_t dsp_sine_dtmf_low[65536];
|
||||
static sample_t dsp_sine_dtmf_high[65536];
|
||||
|
||||
void dtmf_init(dtmf_t *dtmf, int samplerate)
|
||||
{
|
||||
@@ -39,8 +41,10 @@ void dtmf_init(dtmf_t *dtmf, int samplerate)
|
||||
dtmf->max = (int)((double)samplerate * DTMF_DURATION + 0.5);
|
||||
|
||||
// FIXME: do this globally and not per instance */
|
||||
for (i = 0; i < 256; i++)
|
||||
dsp_sine_dtmf[i] = (int)(sin((double)i / 256.0 * 2.0 * PI) * TX_PEAK_DTMF);
|
||||
for (i = 0; i < 65536; i++) {
|
||||
dsp_sine_dtmf_low[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_low;
|
||||
dsp_sine_dtmf_high[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_high;
|
||||
}
|
||||
}
|
||||
|
||||
/* set dtmf tone */
|
||||
@@ -71,8 +75,8 @@ void dtmf_set_tone(dtmf_t *dtmf, char tone)
|
||||
}
|
||||
dtmf->tone = tone;
|
||||
dtmf->pos = 0;
|
||||
dtmf->phaseshift256[0] = 256.0 / ((double)dtmf->samplerate / f1);
|
||||
dtmf->phaseshift256[1] = 256.0 / ((double)dtmf->samplerate / f2);
|
||||
dtmf->phaseshift65536[0] = 65536.0 / ((double)dtmf->samplerate / f1);
|
||||
dtmf->phaseshift65536[1] = 65536.0 / ((double)dtmf->samplerate / f2);
|
||||
}
|
||||
|
||||
/* Generate audio stream from DTMF tone. Keep phase for next call of function. */
|
||||
@@ -87,20 +91,20 @@ void dtmf_tone(dtmf_t *dtmf, sample_t *samples, int length)
|
||||
return;
|
||||
}
|
||||
|
||||
phaseshift = dtmf->phaseshift256;
|
||||
phase = dtmf->phase256;
|
||||
phaseshift = dtmf->phaseshift65536;
|
||||
phase = dtmf->phase65536;
|
||||
pos = dtmf->pos;
|
||||
max = dtmf->max;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
*samples++ = dsp_sine_dtmf[((uint8_t)phase[0]) & 0xff]
|
||||
+ dsp_sine_dtmf[((uint8_t)phase[1]) & 0xff];
|
||||
*samples++ = dsp_sine_dtmf_low[(uint16_t)phase[0]]
|
||||
+ dsp_sine_dtmf_high[(uint16_t)phase[1]];
|
||||
phase[0] += phaseshift[0];
|
||||
if (phase[0] >= 256)
|
||||
phase[0] -= 256;
|
||||
if (phase[0] >= 65536)
|
||||
phase[0] -= 65536;
|
||||
phase[1] += phaseshift[1];
|
||||
if (phase[1] >= 256)
|
||||
phase[1] -= 256;
|
||||
if (phase[1] >= 65536)
|
||||
phase[1] -= 65536;
|
||||
|
||||
/* tone ends */
|
||||
if (++pos == max) {
|
||||
|
@@ -4,8 +4,8 @@ typedef struct dtmf {
|
||||
char tone; /* current tone to be played */
|
||||
int pos; /* sample counter for tone */
|
||||
int max; /* max number of samples for tone duration */
|
||||
double phaseshift256[2]; /* how much the phase of sine wave changes per sample */
|
||||
double phase256[2]; /* current phase */
|
||||
double phaseshift65536[2]; /* how much the phase of sine wave changes per sample */
|
||||
double phase65536[2]; /* current phase */
|
||||
} dtmf_t;
|
||||
|
||||
void dtmf_init(dtmf_t *dtmf, int samplerate);
|
||||
|
@@ -21,6 +21,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "sample.h"
|
||||
#include "filter.h"
|
||||
#include "emphasis.h"
|
||||
#include "debug.h"
|
||||
@@ -29,7 +30,7 @@
|
||||
|
||||
#define CUT_OFF_H 100.0 /* cut-off frequency for high-pass filter */
|
||||
|
||||
static void gen_sine(double *samples, int num, int samplerate, double freq)
|
||||
static void gen_sine(sample_t *samples, int num, int samplerate, double freq)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -37,7 +38,7 @@ static void gen_sine(double *samples, int num, int samplerate, double freq)
|
||||
samples[i] = cos(2.0 * M_PI * freq / (double)samplerate * (double)i);
|
||||
}
|
||||
|
||||
static double get_level(double *samples, int num)
|
||||
static double get_level(sample_t *samples, int num)
|
||||
{
|
||||
int i;
|
||||
double envelope = 0;
|
||||
@@ -52,7 +53,7 @@ static double get_level(double *samples, int num)
|
||||
int init_emphasis(emphasis_t *state, int samplerate, double cut_off)
|
||||
{
|
||||
double factor;
|
||||
double test_samples[samplerate / 10];
|
||||
sample_t test_samples[samplerate / 10];
|
||||
|
||||
memset(state, 0, sizeof(*state));
|
||||
|
||||
@@ -78,7 +79,7 @@ int init_emphasis(emphasis_t *state, int samplerate, double cut_off)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pre_emphasis(emphasis_t *state, double *samples, int num)
|
||||
void pre_emphasis(emphasis_t *state, sample_t *samples, int num)
|
||||
{
|
||||
double x, y, x_last, factor, amp;
|
||||
int i;
|
||||
@@ -101,7 +102,7 @@ void pre_emphasis(emphasis_t *state, double *samples, int num)
|
||||
state->p.x_last = x_last;
|
||||
}
|
||||
|
||||
void de_emphasis(emphasis_t *state, double *samples, int num)
|
||||
void de_emphasis(emphasis_t *state, sample_t *samples, int num)
|
||||
{
|
||||
double x, y, y_last, factor, amp;
|
||||
int i;
|
||||
@@ -125,7 +126,7 @@ void de_emphasis(emphasis_t *state, double *samples, int num)
|
||||
}
|
||||
|
||||
/* high pass filter to remove DC and low frequencies */
|
||||
void dc_filter(emphasis_t *state, double *samples, int num)
|
||||
void dc_filter(emphasis_t *state, sample_t *samples, int num)
|
||||
{
|
||||
filter_process(&state->d.hp, samples, num);
|
||||
}
|
||||
|
@@ -15,7 +15,7 @@ typedef struct emphasis {
|
||||
#define CUT_OFF_EMPHASIS_DEFAULT 300.0
|
||||
|
||||
int init_emphasis(emphasis_t *state, int samplerate, double cut_off);
|
||||
void pre_emphasis(emphasis_t *state, double *samples, int num);
|
||||
void de_emphasis(emphasis_t *state, double *samples, int num);
|
||||
void dc_filter(emphasis_t *state, double *samples, int num);
|
||||
void pre_emphasis(emphasis_t *state, sample_t *samples, int num);
|
||||
void de_emphasis(emphasis_t *state, sample_t *samples, int num);
|
||||
void dc_filter(emphasis_t *state, sample_t *samples, int num);
|
||||
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "sample.h"
|
||||
#include "filter.h"
|
||||
|
||||
#define PI M_PI
|
||||
@@ -65,7 +66,7 @@ void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int it
|
||||
bq->b2 = (1 - K / Q + K * K) * norm;
|
||||
}
|
||||
|
||||
void filter_process(filter_t *bq, double *samples, int length)
|
||||
void filter_process(filter_t *bq, sample_t *samples, int length)
|
||||
{
|
||||
double a0, a1, a2, b1, b2;
|
||||
double *z1, *z2;
|
||||
|
@@ -9,6 +9,6 @@ typedef struct filter {
|
||||
|
||||
void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
||||
void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations);
|
||||
void filter_process(filter_t *bq, double *samples, int length);
|
||||
void filter_process(filter_t *bq, sample_t *samples, int length);
|
||||
|
||||
#endif /* _FILTER_H */
|
||||
|
@@ -1,27 +1,64 @@
|
||||
/* Sample definition
|
||||
*
|
||||
* (C) 2017 by Andreas Eversberg <jolly@eversberg.eu>
|
||||
* All Rights Reserved
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sample.h"
|
||||
#include "sample.h"
|
||||
|
||||
/*
|
||||
* A regular voice conversation takes place at this factor below the full range
|
||||
* of 16 bits signed value:
|
||||
*/
|
||||
static double int_16_speech_level = SPEECH_LEVEL * 0.7079; /* 16 dBm below dBm0, which is about 3dBm below full 16 bit range */
|
||||
|
||||
/* A sample_t is a value that has virtually infinite precision but will also
|
||||
* support high numbers. 'double' or 'float' types are sufficient.
|
||||
*
|
||||
* When using sample_t inside signal processing of each base station, the
|
||||
* level of +- 1 is relative to the normal speach evenlope.
|
||||
*
|
||||
* When converting sample_t to int16_t, the level of +- 1 is reduced by factor.
|
||||
* This way the speech may be louder before clipping happens.
|
||||
*
|
||||
* When using sample_t to modulate (SDR or sound card), the level is changed,
|
||||
* so it represents the frequency deviation in Hz. The deviation of speech
|
||||
* envelope is network dependant.
|
||||
*/
|
||||
|
||||
void samples_to_int16(int16_t *spl, sample_t *samples, int length)
|
||||
{
|
||||
int32_t value;
|
||||
|
||||
while (length--) {
|
||||
if (*samples > 32767.0)
|
||||
*spl = 32767;
|
||||
else if (*samples < -32767.0)
|
||||
*spl = -32767;
|
||||
value = *samples++ * int_16_speech_level * 32768.0;
|
||||
if (value > 32767.0)
|
||||
*spl++ = 32767;
|
||||
else if (value < -32767.0)
|
||||
*spl++ = -32767;
|
||||
else
|
||||
*spl = (uint16_t)(*samples);
|
||||
samples++;
|
||||
spl++;
|
||||
*spl++ = (uint16_t)value;
|
||||
}
|
||||
}
|
||||
|
||||
void int16_to_samples(sample_t *samples, int16_t *spl, int length)
|
||||
{
|
||||
while (length--) {
|
||||
*samples = (double)(*spl);
|
||||
samples++;
|
||||
spl++;
|
||||
*samples++ = (double)(*spl++) / 32767.0 / int_16_speech_level;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1,6 +1,8 @@
|
||||
|
||||
typedef double sample_t;
|
||||
|
||||
#define SPEECH_LEVEL 0.1585
|
||||
|
||||
void samples_to_int16(int16_t *spl, sample_t *samples, int length);
|
||||
void int16_to_samples(sample_t *samples, int16_t *spl, int length);
|
||||
|
||||
|
@@ -124,7 +124,7 @@ int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sam
|
||||
|
||||
if (input == output) {
|
||||
/* copy samples */
|
||||
for (i = 0; i < input_num; i++)
|
||||
for (i = 0; i < output_num; i++)
|
||||
*output++ = samples[i];
|
||||
}
|
||||
|
||||
|
@@ -47,7 +47,6 @@ typedef struct sdr {
|
||||
sdr_chan_t *chan; /* settings for all channels */
|
||||
int paging_channel; /* if set, points to paging channel */
|
||||
sdr_chan_t paging_chan; /* settings for extra paging channel */
|
||||
double spl_deviation; /* how to convert a sample step into deviation (Hz) */
|
||||
int channels; /* number of frequencies */
|
||||
double samplerate; /* IQ rate */
|
||||
double amplitude; /* amplitude of each carrier */
|
||||
@@ -84,15 +83,19 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation)
|
||||
void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double max_deviation, double max_modulation)
|
||||
{
|
||||
sdr_t *sdr;
|
||||
double bandwidth;
|
||||
double tx_center_frequency, rx_center_frequency;
|
||||
int rc;
|
||||
int c;
|
||||
|
||||
display_iq_init(samplerate);
|
||||
|
||||
bandwidth = 2.0 * (max_deviation + max_modulation);
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using Bandwidth of 2 * (%.1f + %.1f) = %.1f\n", max_deviation / 1000, max_modulation / 1000, bandwidth / 1000);
|
||||
|
||||
if (channels < 1) {
|
||||
PDEBUG(DSDR, DEBUG_ERROR, "No channel given, please fix!\n");
|
||||
abort();
|
||||
@@ -105,7 +108,6 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||
}
|
||||
sdr->channels = channels;
|
||||
sdr->samplerate = samplerate;
|
||||
sdr->spl_deviation = sample_deviation;
|
||||
sdr->amplitude = 0.4 / (double)channels; // FIXME: actual amplitude 0.1?
|
||||
|
||||
/* special case where we use a paging frequency */
|
||||
@@ -124,8 +126,8 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX = %.6f MHz, RX = %.6f MHz\n", c, tx_frequency[c] / 1e6, rx_frequency[c] / 1e6);
|
||||
sdr->chan[c].tx_frequency = tx_frequency[c];
|
||||
sdr->chan[c].rx_frequency = rx_frequency[c];
|
||||
filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate, 1);
|
||||
filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate, 1);
|
||||
filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth / 2.0, samplerate, 1);
|
||||
filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth / 2.0, samplerate, 1);
|
||||
}
|
||||
if (sdr->paging_channel) {
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6);
|
||||
@@ -190,21 +192,21 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
|
||||
PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain);
|
||||
|
||||
if (sdr_write_iq_rx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2);
|
||||
rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (sdr_write_iq_tx_wave) {
|
||||
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2);
|
||||
rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (sdr_read_iq_rx_wave) {
|
||||
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2);
|
||||
rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2, 1.0);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||
goto error;
|
||||
@@ -269,7 +271,7 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr
|
||||
/* modulate */
|
||||
for (s = 0, ss = 0; s < num; s++) {
|
||||
/* deviation is defined by the sample value and the offset */
|
||||
dev = offset + (double)samples[c][s] * sdr->spl_deviation;
|
||||
dev = offset + samples[c][s];
|
||||
#ifdef FAST_SINE
|
||||
phase += 256.0 * dev / rate;
|
||||
if (phase < 0.0)
|
||||
@@ -294,20 +296,8 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr
|
||||
if (sdr->wave_tx_rec.fp) {
|
||||
sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] };
|
||||
for (s = 0, ss = 0; s < num; s++) {
|
||||
if (buff[ss] >= 1.0)
|
||||
spl[0][s] = 32767.0;
|
||||
else if (buff[ss] <= -1.0)
|
||||
spl[0][s] = -32767.0;
|
||||
else
|
||||
spl[0][s] = 32767.0 * buff[ss];
|
||||
ss++;
|
||||
if (buff[ss] >= 1.0)
|
||||
spl[1][s] = 32767.0;
|
||||
else if (buff[ss] <= -1.0)
|
||||
spl[1][s] = -32767.0;
|
||||
else
|
||||
spl[1][s] = 32767.0 * buff[ss];
|
||||
ss++;
|
||||
spl[0][s] = buff[ss++];
|
||||
spl[1][s] = buff[ss++];
|
||||
}
|
||||
wave_write(&sdr->wave_tx_rec, spl_list, num);
|
||||
}
|
||||
@@ -325,7 +315,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||
{
|
||||
sdr_t *sdr = (sdr_t *)inst;
|
||||
float buff[num * 2];
|
||||
double I[num], Q[num], i, q;
|
||||
sample_t I[num], Q[num], i, q;
|
||||
int count;
|
||||
int c, s, ss;
|
||||
double phase, rot, last_phase, dev, rate;
|
||||
@@ -341,20 +331,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||
if (sdr->wave_rx_rec.fp) {
|
||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||
for (s = 0, ss = 0; s < count; s++) {
|
||||
if (buff[ss] >= 1.0)
|
||||
spl[0][s] = 32767.0;
|
||||
else if (buff[ss] <= -1.0)
|
||||
spl[0][s] = -32767.0;
|
||||
else
|
||||
spl[0][s] = 32767.0 * buff[ss];
|
||||
ss++;
|
||||
if (buff[ss] >= 1.0)
|
||||
spl[1][s] = 32767.0;
|
||||
else if (buff[ss] <= -1.0)
|
||||
spl[1][s] = -32767.0;
|
||||
else
|
||||
spl[1][s] = 32767.0 * buff[ss];
|
||||
ss++;
|
||||
spl[0][s] = buff[ss++];
|
||||
spl[1][s] = buff[ss++];
|
||||
}
|
||||
wave_write(&sdr->wave_rx_rec, spl_list, count);
|
||||
}
|
||||
@@ -362,8 +340,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||
sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] };
|
||||
wave_read(&sdr->wave_rx_play, spl_list, count);
|
||||
for (s = 0, ss = 0; s < count; s++) {
|
||||
buff[ss++] = spl[0][s] / 32767.0;
|
||||
buff[ss++] = spl[1][s] / 32767.0;
|
||||
buff[ss++] = spl[0][s];
|
||||
buff[ss++] = spl[1][s];
|
||||
}
|
||||
}
|
||||
display_iq(buff, count);
|
||||
@@ -391,7 +369,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels)
|
||||
else if (dev > 0.49)
|
||||
dev -= 1.0;
|
||||
dev *= rate;
|
||||
samples[c][s] = dev / sdr->spl_deviation;
|
||||
samples[c][s] = dev;
|
||||
}
|
||||
sdr->chan[c].rx_last_phase = last_phase;
|
||||
}
|
||||
|
@@ -41,8 +41,6 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf
|
||||
sender->kanal = kanal;
|
||||
sender->sendefrequenz = sendefrequenz;
|
||||
sender->empfangsfrequenz = empfangsfrequenz;
|
||||
sender->bandwidth = 4000; /* default is overwritten by dsp.c */
|
||||
sender->sample_deviation = 0.2; /* default is overwritten by dsp.c */
|
||||
strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1);
|
||||
sender->samplerate = samplerate;
|
||||
sender->rx_gain = rx_gain;
|
||||
@@ -168,21 +166,21 @@ int sender_open_audio(void)
|
||||
}
|
||||
|
||||
if (master->write_rx_wave) {
|
||||
rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels);
|
||||
rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels, master->max_deviation);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (master->write_tx_wave) {
|
||||
rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels);
|
||||
rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels, master->max_deviation);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if (master->read_rx_wave) {
|
||||
rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels);
|
||||
rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels, master->max_deviation);
|
||||
if (rc < 0) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n");
|
||||
return rc;
|
||||
@@ -190,7 +188,7 @@ int sender_open_audio(void)
|
||||
}
|
||||
|
||||
/* open device */
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation);
|
||||
master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->max_deviation, master->max_modulation);
|
||||
if (!master->audio) {
|
||||
PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n");
|
||||
return -EIO;
|
||||
@@ -225,6 +223,17 @@ void sender_destroy(sender_t *sender)
|
||||
jitter_destroy(&sender->dejitter);
|
||||
}
|
||||
|
||||
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display)
|
||||
{
|
||||
sender->max_deviation = max_deviation;
|
||||
sender->max_modulation = max_modulation;
|
||||
sender->dBm0_deviation = dBm0_deviation;
|
||||
sender->max_display = max_display;
|
||||
|
||||
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Maxium deviation: %.1f kHz, Maximum modulation: %.1f kHz\n", max_deviation / 1000.0, max_modulation / 1000.0);
|
||||
PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Deviation at dBm0 (audio level): %.1f kHz\n", dBm0_deviation / 1000.0);
|
||||
}
|
||||
|
||||
static void gain_samples(sample_t *samples, int length, double gain)
|
||||
{
|
||||
int i;
|
||||
@@ -278,12 +287,14 @@ cant_recover:
|
||||
sender_send(inst, samples[i], count);
|
||||
/* internal loopback: loop back TX audio to RX */
|
||||
if (inst->loopback == 1) {
|
||||
display_wave(inst, samples[i], count);
|
||||
display_wave(inst, samples[i], count, inst->max_display);
|
||||
sender_receive(inst, samples[i], count);
|
||||
}
|
||||
/* do pre emphasis towards radio */
|
||||
if (inst->pre_emphasis)
|
||||
pre_emphasis(&inst->estate, samples[i], count);
|
||||
/* normal level to frequency deviation of dBm0 */
|
||||
gain_samples(samples[i], count, inst->dBm0_deviation);
|
||||
/* set paging signal */
|
||||
paging_signal[i] = inst->paging_signal;
|
||||
on[i] = inst->paging_on;
|
||||
@@ -328,6 +339,8 @@ transmit_later:
|
||||
|
||||
/* loop through all channels */
|
||||
for (i = 0, inst = sender; inst; i++, inst = inst->slave) {
|
||||
/* frequency deviation of dBm0 to normal level */
|
||||
gain_samples(samples[i], count, 1.0 / inst->dBm0_deviation);
|
||||
/* rx gain */
|
||||
if (inst->rx_gain != 1.0)
|
||||
gain_samples(samples[i], count, inst->rx_gain);
|
||||
@@ -337,7 +350,7 @@ transmit_later:
|
||||
de_emphasis(&inst->estate, samples[i], count);
|
||||
}
|
||||
if (inst->loopback != 1) {
|
||||
display_wave(inst, samples[i], count);
|
||||
display_wave(inst, samples[i], count, inst->max_display);
|
||||
sender_receive(inst, samples[i], count);
|
||||
}
|
||||
if (inst->loopback == 3)
|
||||
|
@@ -31,8 +31,12 @@ typedef struct sender {
|
||||
double sendefrequenz; /* transmitter frequency */
|
||||
double empfangsfrequenz; /* receiver frequency */
|
||||
double ruffrequenz; /* special paging frequency used for B-Netz */
|
||||
double bandwidth; /* max NF frequency to be transmitted unaffected by filtering */
|
||||
double sample_deviation; /* frequency deviation of one sample step (after pre-emphasis) */
|
||||
|
||||
/* fm levels */
|
||||
double max_deviation; /* max frequency deviation */
|
||||
double max_modulation; /* max frequency modulated */
|
||||
double dBm0_deviation; /* deviation of 1000 Hz reference tone at dBm0 */
|
||||
double max_display; /* level of displaying wave form */
|
||||
|
||||
/* audio */
|
||||
void *audio;
|
||||
@@ -85,6 +89,7 @@ extern int cant_recover;
|
||||
|
||||
int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum paging_signal paging_signal);
|
||||
void sender_destroy(sender_t *sender);
|
||||
void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display);
|
||||
int sender_open_audio(void);
|
||||
void process_sender_audio(sender_t *sender, int *quit, int latspl);
|
||||
void sender_send(sender_t *sender, sample_t *samples, int count);
|
||||
|
@@ -27,6 +27,7 @@
|
||||
typedef struct sound {
|
||||
snd_pcm_t *phandle, *chandle;
|
||||
int pchannels, cchannels;
|
||||
double spl_deviation; /* how much deviation is one sample step */
|
||||
double paging_phaseshift; /* phase to shift every sample */
|
||||
double paging_phase; /* current phase */
|
||||
} sound_t;
|
||||
@@ -131,7 +132,7 @@ static int sound_prepare(sound_t *sound)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double __attribute__((unused)) bandwidth, double __attribute__((unused)) sample_deviation)
|
||||
void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double max_deviation, double __attribute__((unused)) max_modulation)
|
||||
{
|
||||
sound_t *sound;
|
||||
int rc;
|
||||
@@ -147,6 +148,7 @@ void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_freque
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sound->spl_deviation = max_deviation / 32767.0;
|
||||
sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0);
|
||||
|
||||
rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
|
||||
@@ -252,6 +254,7 @@ static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum p
|
||||
int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels)
|
||||
{
|
||||
sound_t *sound = (sound_t *)inst;
|
||||
double spl_deviation = sound->spl_deviation;
|
||||
int32_t value;
|
||||
int16_t buff[num << 1];
|
||||
int rc;
|
||||
@@ -263,7 +266,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||
int16_t paging[num << 1];
|
||||
gen_paging_tone(sound, paging, num, paging_signal[0], on[0]);
|
||||
for (i = 0, ii = 0; i < num; i++) {
|
||||
value = samples[0][i];
|
||||
value = samples[0][i] / spl_deviation;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
@@ -273,13 +276,13 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||
}
|
||||
} else if (channels == 2) {
|
||||
for (i = 0, ii = 0; i < num; i++) {
|
||||
value = samples[0][i];
|
||||
value = samples[0][i] / spl_deviation;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
value = -32767;
|
||||
buff[ii++] = value;
|
||||
value = samples[1][i];
|
||||
value = samples[1][i] / spl_deviation;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
@@ -288,7 +291,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||
}
|
||||
} else {
|
||||
for (i = 0, ii = 0; i < num; i++) {
|
||||
value = samples[0][i];
|
||||
value = samples[0][i] / spl_deviation;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
@@ -300,7 +303,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||
} else {
|
||||
/* one channel */
|
||||
for (i = 0, ii = 0; i < num; i++) {
|
||||
value = samples[0][i];
|
||||
value = samples[0][i] / spl_deviation;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
@@ -328,6 +331,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag
|
||||
int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||
{
|
||||
sound_t *sound = (sound_t *)inst;
|
||||
double spl_deviation = sound->spl_deviation;
|
||||
int16_t buff[num << 1];
|
||||
int32_t spl;
|
||||
int in, rc;
|
||||
@@ -361,17 +365,17 @@ int sound_read(void *inst, sample_t **samples, int num, int channels)
|
||||
for (i = 0, ii = 0; i < rc; i++) {
|
||||
spl = buff[ii++];
|
||||
spl += buff[ii++];
|
||||
samples[0][i] = (sample_t)spl;
|
||||
samples[0][i] = (double)spl * spl_deviation;
|
||||
}
|
||||
} else {
|
||||
for (i = 0, ii = 0; i < rc; i++) {
|
||||
samples[0][i] = (sample_t)buff[ii++];
|
||||
samples[1][i] = (sample_t)buff[ii++];
|
||||
samples[0][i] = (double)buff[ii++] * spl_deviation;
|
||||
samples[1][i] = (double)buff[ii++] * spl_deviation;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (i = 0, ii = 0; i < rc; i++) {
|
||||
samples[0][i] = (sample_t)buff[ii++];
|
||||
samples[0][i] = (double)buff[ii++] * spl_deviation;
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -34,7 +34,7 @@ struct fmt {
|
||||
uint16_t bits_sample; /* bits per sample (one channel) */
|
||||
};
|
||||
|
||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels)
|
||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation)
|
||||
{
|
||||
/* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */
|
||||
char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4];
|
||||
@@ -43,6 +43,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in
|
||||
memset(rec, 0, sizeof(*rec));
|
||||
rec->samplerate = samplerate;
|
||||
rec->channels = channels;
|
||||
rec->max_deviation = max_deviation;
|
||||
|
||||
rec->fp = fopen(filename, "w");
|
||||
if (!rec->fp) {
|
||||
@@ -58,7 +59,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels)
|
||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation)
|
||||
{
|
||||
uint8_t buffer[256];
|
||||
struct fmt fmt;
|
||||
@@ -68,6 +69,7 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate
|
||||
|
||||
memset(play, 0, sizeof(*play));
|
||||
play->channels = channels;
|
||||
play->max_deviation = max_deviation;
|
||||
|
||||
play->fp = fopen(filename, "r");
|
||||
if (!play->fp) {
|
||||
@@ -196,6 +198,8 @@ error:
|
||||
|
||||
int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||
{
|
||||
double max_deviation = play->max_deviation;
|
||||
int16_t value; /* must be int16, so assembling bytes work */
|
||||
uint8_t buff[2 * length * play->channels];
|
||||
int __attribute__((__unused__)) len;
|
||||
int i, j, c;
|
||||
@@ -212,11 +216,12 @@ int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||
if (!play->left)
|
||||
printf("*** Finished reading WAVE file.\n");
|
||||
|
||||
/* read and correct endiness */
|
||||
/* read and correct endianness */
|
||||
len = fread(buff, 1, 2 * length * play->channels, play->fp);
|
||||
for (i = 0, j = 0; i < length; i++) {
|
||||
for (c = 0; c < play->channels; c++) {
|
||||
samples[c][i] = (double)(buff[j] + (buff[j + 1] << 8));
|
||||
value = buff[j] + (buff[j + 1] << 8);
|
||||
samples[c][i] = (double)value / 32767.0 * max_deviation;
|
||||
j += 2;
|
||||
}
|
||||
}
|
||||
@@ -226,15 +231,16 @@ int wave_read(wave_play_t *play, sample_t **samples, int length)
|
||||
|
||||
int wave_write(wave_rec_t *rec, sample_t **samples, int length)
|
||||
{
|
||||
double max_deviation = rec->max_deviation;
|
||||
int32_t value;
|
||||
uint8_t buff[2 * length * rec->channels];
|
||||
int __attribute__((__unused__)) len;
|
||||
int i, j, c;
|
||||
|
||||
/* write and correct endiness */
|
||||
/* write and correct endianness */
|
||||
for (i = 0, j = 0; i < length; i++) {
|
||||
for (c = 0; c < rec->channels; c++) {
|
||||
value = samples[c][i];
|
||||
value = samples[c][i] / max_deviation * 32767.0;
|
||||
if (value > 32767)
|
||||
value = 32767;
|
||||
else if (value < -32767)
|
||||
|
@@ -2,6 +2,7 @@
|
||||
typedef struct wave_rec {
|
||||
FILE *fp;
|
||||
int channels;
|
||||
double max_deviation;
|
||||
int samplerate;
|
||||
uint32_t written; /* how much samples written */
|
||||
} wave_rec_t;
|
||||
@@ -9,11 +10,12 @@ typedef struct wave_rec {
|
||||
typedef struct wave_play {
|
||||
FILE *fp;
|
||||
int channels;
|
||||
double max_deviation;
|
||||
uint32_t left; /* how much samples left */
|
||||
} wave_play_t;
|
||||
|
||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels);
|
||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels);
|
||||
int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation);
|
||||
int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation);
|
||||
int wave_read(wave_play_t *play, sample_t **samples, int length);
|
||||
int wave_write(wave_rec_t *rec, sample_t **samples, int length);
|
||||
void wave_destroy_record(wave_rec_t *rec);
|
||||
|
Reference in New Issue
Block a user