Connect to the oscillator of the transmitter - good girl! You need to enable pre emphasis in this case. Connect to the discriminator of the receiver - good boy! You need to enable de emphasis in this case.pull/1/head
parent
5062628e52
commit
4356c93afa
@ -0,0 +1,102 @@ |
||||
/* Pre-Emphasis and De-Emphasis implementation
|
||||
* |
||||
* (C) 2016 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 <stdio.h> |
||||
#include <stdint.h> |
||||
#include <string.h> |
||||
#include <math.h> |
||||
#include "emphasis.h" |
||||
#include "debug.h" |
||||
|
||||
|
||||
int init_emphasis(emphasis_t *state, int samplerate) |
||||
{ |
||||
double factor; |
||||
|
||||
memset(state, 0, sizeof(*state)); |
||||
if (samplerate < 24000) { |
||||
PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 24000 Hz!\n"); |
||||
return -1; |
||||
} |
||||
|
||||
factor = 0.95; |
||||
state->p.factor = factor; |
||||
state->p.amp = samplerate / 48000.0 * 4.0; /* mysterious 48000 */ |
||||
state->d.factor = factor; |
||||
state->d.amp = 1.0 / (samplerate / 48000.0 * 4.0); /* mysterious 48000 */ |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
void pre_emphasis(emphasis_t *state, int16_t *samples, int num) |
||||
{ |
||||
int32_t sample; |
||||
double old_value, new_value, last_value, factor, amp; |
||||
int i; |
||||
|
||||
last_value = state->p.last_value; |
||||
factor = state->p.factor; |
||||
amp = state->p.amp; |
||||
|
||||
for (i = 0; i < num; i++) { |
||||
old_value = (double)(*samples) / 32768.0; |
||||
|
||||
new_value = old_value - factor * last_value; |
||||
|
||||
last_value = old_value; |
||||
|
||||
sample = (int)(amp * new_value * 32768.0); |
||||
if (sample > 32767) |
||||
sample = 32767; |
||||
else if (sample < -32768) |
||||
sample = -32768; |
||||
*samples++ = sample; |
||||
} |
||||
|
||||
state->p.last_value = last_value; |
||||
} |
||||
|
||||
void de_emphasis(emphasis_t *state, int16_t *samples, int num) |
||||
{ |
||||
int32_t sample; |
||||
double old_value, new_value, last_value, factor, amp; |
||||
int i; |
||||
|
||||
last_value = state->d.last_value; |
||||
factor = state->d.factor; |
||||
amp = state->d.amp; |
||||
|
||||
for (i = 0; i < num; i++) { |
||||
old_value = (double)(*samples) / 32768.0; |
||||
|
||||
new_value = old_value + factor * last_value; |
||||
|
||||
last_value = new_value; |
||||
|
||||
sample = (int)(amp * new_value * 32768.0); |
||||
if (sample > 32767) |
||||
sample = 32767; |
||||
else if (sample < -32768) |
||||
sample = -32768; |
||||
*samples++ = sample; |
||||
} |
||||
|
||||
state->d.last_value = last_value; |
||||
} |
||||
|
@ -0,0 +1,17 @@ |
||||
typedef struct emphasis { |
||||
struct { |
||||
double last_value; |
||||
double factor; |
||||
double amp; |
||||
} p; |
||||
struct { |
||||
double last_value; |
||||
double factor; |
||||
double amp; |
||||
} d; |
||||
} emphasis_t; |
||||
|
||||
int init_emphasis(emphasis_t *state, int samplerate); |
||||
void pre_emphasis(emphasis_t *state, int16_t *samples, int num); |
||||
void de_emphasis(emphasis_t *state, int16_t *samples, int num); |
||||
|
@ -0,0 +1,75 @@ |
||||
#include <stdio.h> |
||||
#include <stdint.h> |
||||
#include <math.h> |
||||
#include <string.h> |
||||
#include "../common/emphasis.h" |
||||
|
||||
#define level2db(level) (20 * log10(level)) |
||||
#define db2level(db) pow(10, (double)db / 20.0) |
||||
|
||||
#define SAMPLERATE 48000 |
||||
#define DEVIATION 8000.0 |
||||
|
||||
static void check_level(int16_t *samples, const char *desc) |
||||
{ |
||||
int i; |
||||
int last = 0, envelope = 0; |
||||
int up = 0; |
||||
int freq; |
||||
|
||||
for (i = 0; i < SAMPLERATE; i++) { |
||||
if (last < samples[i]) { |
||||
up = 1; |
||||
} else if (last > samples[i]) { |
||||
if (up) { |
||||
envelope = last; |
||||
} |
||||
up = 0; |
||||
} |
||||
if ((i % (SAMPLERATE/40)) == 0) { |
||||
freq = 500 + 500 * (i / (SAMPLERATE / 8)); |
||||
printf("%s: f = %d envelop = %.4f\n", desc, freq, level2db((double)envelope / DEVIATION)); |
||||
} |
||||
last = samples[i]; |
||||
} |
||||
} |
||||
|
||||
static void gen_samples(int16_t *samples) |
||||
{ |
||||
int i; |
||||
double value; |
||||
int freq; |
||||
|
||||
for (i = 0; i < SAMPLERATE; i++) { |
||||
freq = 500 + 500 * (i / (SAMPLERATE / 8)); |
||||
value = sin(2.0 * M_PI * (double)freq / (double)SAMPLERATE * (double)i); |
||||
samples[i] = value * DEVIATION; |
||||
} |
||||
} |
||||
|
||||
int main(void) |
||||
{ |
||||
emphasis_t estate; |
||||
int16_t samples[SAMPLERATE]; |
||||
|
||||
/* generate sweep 0..4khz */ |
||||
gen_samples(samples); |
||||
|
||||
init_emphasis(&estate, SAMPLERATE); |
||||
|
||||
// check_level(samples, "unchanged");
|
||||
|
||||
pre_emphasis(&estate, samples, SAMPLERATE); |
||||
|
||||
check_level(samples, "pre-emphasis"); |
||||
|
||||
/* generate sweep 0..4khz */ |
||||
gen_samples(samples); |
||||
|
||||
de_emphasis(&estate, samples, SAMPLERATE); |
||||
|
||||
check_level(samples, "de-emphasis"); |
||||
|
||||
return 0; |
||||
} |
||||
|
Loading…
Reference in new issue