提交 68913681 authored 作者: Brian West's avatar Brian West

git status -u, learn something new every day.

上级 59205c76
README_fdmdv.txt
David Rowe
Created March 2012
Introduction
------------
A 1400 bit/s Frequency Division Multiplexed Digital Voice (FDMDV) modem
based on [1]. Used for digital audio over HF SSB.
The FDMDV modem was first implemented in GNU Octave, then ported to C.
Algorithm development is generally easier in Octave, but for real time
work we need the C version. Automated units tests ensure the
operation of the Octave and C versions are identical.
Quickstart
----------
$ cd codec2-dev
$ ./configure && make
$ cd src
1. Generate some test bits and modulate them:
$ ./fdmdv_get_test_bits test.c2 1400
$ ./fdmdv_mod test.c2 test.raw
$ play -r 8000 -s -2 test.raw
2. Two seconds of test frame data modulated and sent out of sound device:
$ ./fdmdv_get_test_bits - 2800 | ./fdmdv_mod - - | play -t raw -r 8000 -s -2 -
3. Send 14000 modulated bits (10 seconds) to the demod and count errors:
$ ./fdmdv_get_test_bits - 14000 | ./fdmdv_mod - - | ./fdmdv_demod - - demod_dump.txt | ./fdmdv_put_test_bits -
Use Octave to look at plots of 1 second (1400 bits) of modem operation:
$ cd ../octave
$ octave
octave:1> fdmdv_demod_c("../src/demod_dump.txt",1400)
4. Run Octave simulation of entire modem and AWGN channel:
$ cd ../octave
$ octave
octave:1> fdmdv_ut
5. NOTE: If you would like to play modem samples over the air please
convert the 8 kHz samples to 48 kHz. Many PC sound cards have
wildly inaccurate sample clock rates when set to 8 kHz, but seem to
perform OK when set for 48 kHz. If playing and recording files you
can use the sox utility:
$ sox -r 8000 -s -2 modem_sample_8kHz.raw -r 48000 modem_sample_48kHz.wav
For real time applications, the fdmdv.[ch] library includes functions to
convert between 48 and 8 kHz sample rates.
References
----------
[1] http://n1su.com/fdmdv/FDMDV_Docs_Rel_1_4b.pdf
[2] http://n1su.com/fdmdv/
[3] http://www.rowetel.com/blog/?p=2433 "Testing a FDMDV Modem"
[4] http://www.rowetel.com/blog/?p=2458 "FDMDV Modem Page" on David's web site
C Code
------
src/fdmdv_mod.c - C version of modulator that takes a file of bits and
converts it to a raw file of modulated samples.
src/fdmdv_demod.c - C version of demodulator that takes a raw file of
modulated samples and outputs a file of bits.
Optionally dumps demod states to a text file which
can be plotted using the Octave script
fdmdv_demod_c.m
src/fdmdv.h - Header file that exposes FDMDV C API functions. Include
this file in your application program.
src/fdmdv.c - C functions that implement the FDMDV modem.
src/fdmdv-internal.h - internal states and constants for FDMDV modem,
shouldn't be exposed to application program.
unittest/tfdmdv.c - Used to conjunction with unittest/tfdmdv.m to
automatically test C FDMDV functions against
Octave versions.
Octave Scripts
--------------
(Note these require some Octave packages to be installed, see
octave/README.txt).
fdmdv.m - Functions and variables that implement the Octave version of
the FDMDV modem.
fdmdv_ut.m - Unit test for fdmdv Octave code, useful while
developing algorithm. Includes tx/rx plus basic channel
simulation.
Typical run:
octave:6> fdmdv_ut
Eb/No (meas): 7.30 (8.29) dB
bits........: 2464
errors......: 20
BER.........: 0.0081
PAPR........: 13.54 dB
SNR.........: 4.0 dB
It also outputs lots of nice plots that show the
operation of the modem.
For a 1400 bit/s DQPSK modem we expect about 1% BER for
Eb/No = 7.3dB, which corresponds to SNR = 4dB (3kHz
noise BW). The extra dB of measured power is due to the
DBPSK pilot. Currently the noise generation code
doesn't take the pilot power into account, so in this
example the real SNR is actually 5dB.
fdmdv_mod.m - Octave version of modulator that outputs a raw file.
The modulator is driven by a test frame of bits. This
can then be played over a real channel or through a
channel simulator like PathSim. The sample rate can be
changed using "sox" to simulate differences in tx/rx
sample clocks.
To generate 10 seconds of modulated signal:
octave:8> fdmdv_mod("test.raw",1400*10);
fdmdv_demod.m - Demodulator program that takes a raw file as input,
and works out the bit error rate using the known test
frame. Can be used to test the demod performs with
off-air signals, or signals that have been passed
through a channel simulator.
To demodulate 2 seconds of the test.raw file generated
above:
octave:9> fdmdv_demod("test.raw",1400*2);
2464 bits 0 errors BER: 0.0000
It also produces several plots showing the internal
states of the demod. Useful for debugging and
observing what happens with various channels.
fdmdv_demod_c.m - Takes an output text file from the C demod
fdmdv_demod.c and produces plots and measures BER.
Useful for evaluating fdmdv_demod.c performance.
The plots produced are identical to the Octave
version fdmdv_demod.m, allowing direct comparison of
the C and Octave versions.
tfdmdv.m - Automatic tests that compare the Octave and C versions of
the FDMDV modem functions. First run unittest/tfdmdv, this
will generate a text file with test vectors from the C
version. Then run the Octave script tfdmdv and it will
generate Octave versions of the test vectors and compare
each vector with the C equivalent. Its plots the vectors
and and errors (green). Its also produces an automatic
check list based on test results. If the Octave or C modem
code is changed, this script should be used to ensure the
C and Octave versions remain identical.
Modelling sample clock errors using sox
---------------------------------------
This introduces a simulated 1000ppm error:
sox -r 8000 -s -2 mod_dqpsk.raw -s -2 mod_dqpsk_8008hz.raw rate -h 8008
TODO
----
[ ] implement ppm measurements in fdmdv_get_demod_stats()
[ ] try interfering sine wave
+ maybe swept
+ does modem fall over?
[ ] try non-flat channel, e.g. 3dB difference between hi and low tones
+ make sure all estimators keep working
[ ] test rx level sensitivity, i.e. 0 to 20dB attenuation
[ ] make fine freq indep of amplitude
+ use angle rather than imag coord
[ ] document use of fdmdv_ut and fdmdv_demod + PathSim
[ ] more positive form of sync reqd for DV frames?
+ like using coarse_fine==1 to decode valid DV frame bit?
+ when should we start decoding?
[ ] more robust track/acquite state machine?
+ e.g. hang on thru the fades?
[ ] PAPR idea
+ automatically tweak phases to reduce PAPR, e.g. slow variations in freq...
[ ] why is pilot noise_est twice as big as other carriers
README for codec2/asterisk
Asterisk Codec 2 support
Test Configuration
------------------
Codec 2 is used to trunk calls between two Asterisk boxes:
A - SIP phone - Asterisk A - Codec2 - Asterisk B - SIP Phone - B
The two SIP phones are configured for mulaw.
Building
---------
Asterisk must be patched so that the core understand Codec 2 frames.
1/ First install Codec 2:
david@cool:~$ svn co https://freetel.svn.sourceforge.net/svnroot/freetel/codec2-dev codec2-dev
david@cool:~/codec2-dev$ cd codec2-dev
david@cool:~/codec2-dev$ ./configure && make && sudo make install
david@bear:~/codec2-dev$ sudo ldconfig -v
david@cool:~/codec2-dev$ cd ~
2/ Then build Asterisk with Codec 2 support:
david@cool:~$ tar xvzf asterisk-1.8.9.0.tar.gz
david@cool:~/asterisk-1.8.9.0$ patch -p4 < ~/codec2-dev/asterisk/asterisk-codec2.patch
david@cool:~/asterisk-1.8.9.0$ cp ~/codec2-dev/asterisk/codec_codec2.c .
david@cool:~/asterisk-1.8.9.0$ cp ~/codec2-dev/asterisk/ex_codec2.h ./codecs
david@cool:~/asterisk-1.8.9.0$ ./configure && make ASTLDFLAGS=-lcodec2
david@cool:~/asterisk-1.8.9.0$ sudo make install
david@cool:~/asterisk-1.8.9.0$ sudo make samples
3/ Add this to the end of sip.conf on Asterisk A:
[6013]
type=friend
context=default
host=dynamic
user=6013
secret=6013
canreinvite=no
callerid=6013
disallow=all
allow=ulaw
[potato]
type=peer
username=potato
fromuser=potato
secret=password
context=default
disallow=all
dtmfmode=rfc2833
callerid=server
canreinvite=no
host=cool
allow=codec2
3/ Add this to the end of sip.conf on Asterisk B:
[6014]
type=friend
context=default
host=dynamic
user=6014
secret=6014
canreinvite=no
callerid=6014
disallow=all
allow=ulaw
[potato]
type=peer
username=potato
fromuser=potato
secret=password
context=default
disallow=all
dtmfmode=rfc2833
callerid=server
canreinvite=no
host=bear
allow=codec2
4/ Here is the [default] section of extensions.conf on Asterisk B:
[default]
exten => 6013,1,Dial(SIP/potato/6013)
;
; By default we include the demo. In a production system, you
; probably don't want to have the demo there.
;
;include => demo
5/ After booting see if the codec2_codec2.so module is loaded with "core show translate"
6/ To make a test call dial 6013 on the SIP phone connected to Asterisk B
7/ If codec_codec2.so won't load and you see "can't find codec2_create" try:
david@cool:~/asterisk-1.8.9.0$ touch codecs/codec_codec2.c
david@cool:~/asterisk-1.8.9.0$ make ASTLDFLAGS=-lcodec2
david@cool:~/asterisk-1.8.9.0$ sudo cp codecs/codec_codec2.so /usr/lib/asterisk/modules
david@cool:~/asterisk-1.8.9.0$ sudo asterisk -vvvcn
--- /home/david/asterisk-1.8.9.0-orig/include/asterisk/frame.h 2011-12-23 05:08:46.000000000 +1030
+++ /home/david/asterisk-1.8.9.0-codec2/include/asterisk/frame.h 2012-03-27 13:16:55.623452431 +1030
@@ -299,6 +299,7 @@
#define AST_FORMAT_G719 (1ULL << 32)
/*! SpeeX Wideband (16kHz) Free Compression */
#define AST_FORMAT_SPEEX16 (1ULL << 33)
+#define AST_FORMAT_CODEC2 (1ULL << 34)
/*! Raw mu-law data (G.711) */
#define AST_FORMAT_TESTLAW (1ULL << 47)
/*! Reserved bit - do not use */
--- /home/david/asterisk-1.8.9.0-orig/main/frame.c 2010-06-18 02:53:43.000000000 +0930
+++ /home/david/asterisk-1.8.9.0-codec2/main/frame.c 2012-03-28 15:16:16.975581316 +1030
@@ -102,6 +102,7 @@
{ AST_FORMAT_ADPCM, "adpcm" , 8000, "ADPCM", 40, 10, 300, 10, 20 }, /*!< codec_adpcm.c */
{ AST_FORMAT_SLINEAR, "slin", 8000, "16 bit Signed Linear PCM", 160, 10, 70, 10, 20, AST_SMOOTHER_FLAG_BE }, /*!< Signed linear */
{ AST_FORMAT_LPC10, "lpc10", 8000, "LPC10", 7, 20, 20, 20, 20 }, /*!< codec_lpc10.c */
+ { AST_FORMAT_CODEC2, "codec2", 8000, "Codec 2", 7, 20, 20, 20, 20 }, /*!< codec_codec2.c */
{ AST_FORMAT_G729A, "g729", 8000, "G.729A", 10, 10, 230, 10, 20, AST_SMOOTHER_FLAG_G729 }, /*!< Binary commercial distribution */
{ AST_FORMAT_SPEEX, "speex", 8000, "SpeeX", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
{ AST_FORMAT_SPEEX16, "speex16", 16000, "SpeeX 16khz", 10, 10, 60, 10, 20 }, /*!< codec_speex.c */
@@ -1475,6 +1476,9 @@
samples = 22 * 8;
samples += (((char *)(f->data.ptr))[7] & 0x1) * 8;
break;
+ case AST_FORMAT_CODEC2:
+ samples = 160 * (f->datalen / 7);
+ break;
case AST_FORMAT_ULAW:
case AST_FORMAT_ALAW:
case AST_FORMAT_TESTLAW:
@@ -1519,6 +1523,9 @@
case AST_FORMAT_GSM:
len = (samples / 160) * 33;
break;
+ case AST_FORMAT_CODEC2:
+ len = (samples / 160) * 7;
+ break;
case AST_FORMAT_G729A:
len = samples / 8;
break;
--- /home/david/asterisk-1.8.9.0-orig/main/channel.c 2011-12-17 10:21:13.000000000 +1030
+++ /home/david/asterisk-1.8.9.0-codec2/main/channel.c 2012-03-28 15:05:22.395293391 +1030
@@ -1075,6 +1075,7 @@
/*! Ick, LPC10 sounds terrible, but at least we have code for it, if you're tacky enough
to use it */
AST_FORMAT_LPC10,
+ AST_FORMAT_CODEC2,
/*! G.729a is faster than 723 and slightly less expensive */
AST_FORMAT_G729A,
/*! Down to G.723.1 which is proprietary but at least designed for voice */
--- /home/david/asterisk-1.8.9.0-orig/main/rtp_engine.c 2011-12-30 01:43:03.000000000 +1030
+++ /home/david/asterisk-1.8.9.0-codec2/main/rtp_engine.c 2012-03-28 16:42:02.880872891 +1030
@@ -101,6 +101,7 @@
{{1, AST_FORMAT_SLINEAR}, "audio", "L16", 8000},
{{1, AST_FORMAT_SLINEAR16}, "audio", "L16", 16000},
{{1, AST_FORMAT_LPC10}, "audio", "LPC", 8000},
+ {{1, AST_FORMAT_CODEC2}, "audio", "CODEC2", 8000},
{{1, AST_FORMAT_G729A}, "audio", "G729", 8000},
{{1, AST_FORMAT_G729A}, "audio", "G729A", 8000},
{{1, AST_FORMAT_G729A}, "audio", "G.729", 8000},
@@ -178,6 +179,7 @@
[117] = {1, AST_FORMAT_SPEEX16},
[118] = {1, AST_FORMAT_SLINEAR16}, /* 16 Khz signed linear */
[121] = {0, AST_RTP_CISCO_DTMF}, /* Must be type 121 */
+ [121] = {1, AST_FORMAT_CODEC2},
};
int ast_rtp_engine_register2(struct ast_rtp_engine *engine, struct ast_module *module)
/*
* Codec 2 module for Asterisk.
*
* Credit: codec_gsm.c used as a starting point.
*
* Copyright (C) 2012 Ed W and David Rowe
*
* This program is free software, distributed under the terms of
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree.
*/
/*! \file
*
* \brief Translate between signed linear and Codec 2
*
* \ingroup codecs
*/
/*** MODULEINFO
<support_level>core</support_level>
***/
#include "asterisk.h"
#include "asterisk/translate.h"
#include "asterisk/config.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include <codec2.h>
#define BUFFER_SAMPLES 8000
#define CODEC2_SAMPLES 160
#define CODEC2_FRAME_LEN 7
/* Sample frame data */
#include "asterisk/slin.h"
#include "ex_codec2.h"
struct codec2_translator_pvt { /* both codec2tolin and codec2togsm */
struct CODEC2 *codec2;
short buf[BUFFER_SAMPLES]; /* lintocodec2, temporary storage */
};
static int codec2_new(struct ast_trans_pvt *pvt)
{
struct codec2_translator_pvt *tmp = pvt->pvt;
tmp->codec2 = codec2_create(CODEC2_MODE_2400);
return 0;
}
/*! \brief decode and store in outbuf. */
static int codec2tolin_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec2_translator_pvt *tmp = pvt->pvt;
int x;
int16_t *dst = pvt->outbuf.i16;
int flen = CODEC2_FRAME_LEN;
for (x=0; x < f->datalen; x += flen) {
unsigned char *src;
int len;
len = CODEC2_SAMPLES;
src = f->data.ptr + x;
codec2_decode(tmp->codec2, dst + pvt->samples, src);
pvt->samples += CODEC2_SAMPLES;
pvt->datalen += 2 * CODEC2_SAMPLES;
}
return 0;
}
/*! \brief store samples into working buffer for later decode */
static int lintocodec2_framein(struct ast_trans_pvt *pvt, struct ast_frame *f)
{
struct codec2_translator_pvt *tmp = pvt->pvt;
if (pvt->samples + f->samples > BUFFER_SAMPLES) {
ast_log(LOG_WARNING, "Out of buffer space\n");
return -1;
}
memcpy(tmp->buf + pvt->samples, f->data.ptr, f->datalen);
pvt->samples += f->samples;
return 0;
}
/*! \brief encode and produce a frame */
static struct ast_frame *lintocodec2_frameout(struct ast_trans_pvt *pvt)
{
struct codec2_translator_pvt *tmp = pvt->pvt;
int datalen = 0;
int samples = 0;
/* We can't work on anything less than a frame in size */
if (pvt->samples < CODEC2_SAMPLES)
return NULL;
while (pvt->samples >= CODEC2_SAMPLES) {
/* Encode a frame of data */
codec2_encode(tmp->codec2, (unsigned char*)(pvt->outbuf.c + datalen), tmp->buf + samples);
datalen += CODEC2_FRAME_LEN;
samples += CODEC2_SAMPLES;
pvt->samples -= CODEC2_SAMPLES;
}
/* Move the data at the end of the buffer to the front */
if (pvt->samples)
memmove(tmp->buf, tmp->buf + samples, pvt->samples * 2);
return ast_trans_frameout(pvt, datalen, samples);
}
static void codec2_destroy_stuff(struct ast_trans_pvt *pvt)
{
struct codec2_translator_pvt *tmp = pvt->pvt;
if (tmp->codec2)
codec2_destroy(tmp->codec2);
}
static struct ast_translator codec2tolin = {
.name = "codec2tolin",
.srcfmt = AST_FORMAT_CODEC2,
.dstfmt = AST_FORMAT_SLINEAR,
.newpvt = codec2_new,
.framein = codec2tolin_framein,
.destroy = codec2_destroy_stuff,
.sample = codec2_sample,
.buffer_samples = BUFFER_SAMPLES,
.buf_size = BUFFER_SAMPLES * 2,
.desc_size = sizeof (struct codec2_translator_pvt ),
};
static struct ast_translator lintocodec2 = {
.name = "lintocodec2",
.srcfmt = AST_FORMAT_SLINEAR,
.dstfmt = AST_FORMAT_CODEC2,
.newpvt = codec2_new,
.framein = lintocodec2_framein,
.frameout = lintocodec2_frameout,
.destroy = codec2_destroy_stuff,
.sample = slin8_sample,
.desc_size = sizeof (struct codec2_translator_pvt ),
.buf_size = (BUFFER_SAMPLES * CODEC2_FRAME_LEN + CODEC2_SAMPLES - 1)/CODEC2_SAMPLES,
};
/*! \brief standard module glue */
static int reload(void)
{
return AST_MODULE_LOAD_SUCCESS;
}
static int unload_module(void)
{
int res;
res = ast_unregister_translator(&lintocodec2);
if (!res)
res = ast_unregister_translator(&codec2tolin);
return res;
}
static int load_module(void)
{
int res;
res = ast_register_translator(&codec2tolin);
if (!res)
res=ast_register_translator(&lintocodec2);
else
ast_unregister_translator(&codec2tolin);
if (res)
return AST_MODULE_LOAD_FAILURE;
return AST_MODULE_LOAD_SUCCESS;
}
AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_DEFAULT, "Codec 2 Coder/Decoder",
.load = load_module,
.unload = unload_module,
.reload = reload,
);
/*! \file
* \brief 8-bit raw data
*
* Copyright (C) 2012, 2012 Ed W and David Rowe
*
* Distributed under the terms of the GNU General Public License
*
*/
static uint8_t ex_codec2[] = {
0x3e,0x06,0x4a,0xbb,0x9e,0x40,0xc0
};
static struct ast_frame *codec2_sample(void)
{
static struct ast_frame f = {
.frametype = AST_FRAME_VOICE,
.subclass.codec = AST_FORMAT_CODEC2,
.datalen = sizeof(ex_codec2),
.samples = CODEC2_SAMPLES,
.mallocd = 0,
.offset = 0,
.src = __PRETTY_FUNCTION__,
.data.ptr = ex_codec2,
};
return &f;
}
#!/bin/sh
# Create patch for Codec 2 support inside Asterisk
ORIG=~/asterisk-1.8.9.0-orig
CODEC2=~/asterisk-1.8.9.0-codec2
diff -ruN $ORIG/include/asterisk/frame.h $CODEC2/include/asterisk/frame.h > asterisk-codec2.patch
diff -ruN $ORIG/main/frame.c $CODEC2/main/frame.c >> asterisk-codec2.patch
diff -ruN $ORIG/main/channel.c $CODEC2/main/channel.c >> asterisk-codec2.patch
diff -ruN $ORIG/main/rtp_engine.c $CODEC2/main/rtp_engine.c >> asterisk-codec2.patch
# Requires FLTK 1.3 & Portaudio V19
FLTK_VER = $(shell fltk-config --api-version)
ifneq ($(FLTK_VER),1.3)
$(error Must use FLTK version 1.3, you have $(FLTK_VER))
endif
FLTK_CFLAGS += $(shell fltk-config --ldstaticflags)
CFLAGS = -O3 -g -Wall
LIBS = ../src/.libs/libcodec2.a -lm -lrt -lportaudio -pthread
LC2POC_C = fl_fdmdv.cxx
all: fl_fdmdv
fl_fdmdv: Makefile $(LC2POC_C)
g++ $(LC2POC_C) -I../src/ -o fl_fdmdv $(CFLAGS) $(FLTK_CFLAGS) $(LIBS)
clean:
rm -f fl_fdmdv
差异被折叠。
README.txt
For codec2/octave directory
Created 24 June 2012 by David Rowe
1/ To support some of the Octave scripts (in particular fdmdv) in this
directory the following Octave packages need to be installed:
control image miscellaneous optim signal specfun struct
2/ Download these tar balls from:
http://octave.sourceforge.net/packages.php
3/ Install each package from the Octave command line with:
octave:3> pkg install package_file_name.tar.gz
% av_imp.m
% David Rowe Aug 2012
% Averages the impulse response samples
function imp = av_imp(imp_filename, period_in_secs, st, en)
f = fopen(imp_filename,"rb");
s = fread(f, Inf, "short")';
Fs = 8000;
n = period_in_secs * Fs;
[r c] = size(s);
imp = zeros(1,n);
for i=1:n:c-n
imp = imp + s(i:i+n-1);
endfor
% user supplies start and end samples after viweing plot
if (nargin == 4)
imp = imp(st:en);
end
% normalise
imp /= sqrt(sum(imp .^ 2));
[h w] = freqz(imp, 1, 4000);
figure(1);
clf;
plot(imp);
figure(2);
clf;
subplot(211)
plot(10*log10(abs(h)))
subplot(212)
plot(angle(h))
endfunction
% cbphase.m
% David Rowe Aug 2012
% Used to experiment with critical band phase perception and smoothing
function cbphase
Wo = 100.0*pi/4000;
L = floor(pi/Wo);
A = zeros(1,L);
phi = zeros(1,L);
% three harmonics in this band
b = 4; a = b-1; c = b+1;
% set up phases and mags for 2nd order system (see phasesecord.m)
wres = b*Wo;
phi(a) = 3*pi/4 + wres;
phi(b) = pi/2 + wres;
phi(c) = pi/4 + wres;
A(a) = 0.707;
A(b) = 1;
A(c) = 0.707;
% add linear component
phi(1) = pi;
phi(2:L) = phi(2:L) + (2:L)*phi(1);
phi = phi - 2*pi*(floor(phi/(2*pi)) + 0.5);
N = 16000;
Nplot = 250;
s = zeros(1,N);
for m=a:c
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m));
s = s + s_m;
endfor
figure(2);
clf;
subplot(211)
plot((1:L)*Wo*4000/pi, A,'+');
subplot(212)
plot((1:L)*Wo*4000/pi, phi,'+');
%v = A(a)*exp(j*phi(a)) + A(b)*exp(j*phi(b)) + A(c)*exp(j*phi(c));
%compass(v,"r")
%hold off;
% est phi1
diff = phi(b) - phi(a)
sumi = sin(diff);
sumr = cos(diff);
diff = phi(c) - phi(b)
sumi += sin(diff);
sumr += cos(diff);
phi1_ = atan2(sumi, sumr)
s_v = cos(Wo*(0:(N-1)) + phi1_);
figure(1);
clf;
subplot(211)
plot(s(1:Nplot));
hold on;
plot(s_v(1:Nplot),"r");
hold off;
% build (hopefully) perceptually similar phase
phi_(a) = a*phi1_;
phi_(b) = b*phi1_;
phi_(c) = c*phi1_;
s_ = zeros(1,N);
for m=a:c
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi_(m));
s_ = s_ + s_m;
endfor
subplot(212)
plot(s_(1:Nplot));
gain = 8000;
fs=fopen("orig_ph.raw","wb");
fwrite(fs,gain*s,"short");
fclose(fs);
fs=fopen("mod_ph.raw","wb");
fwrite(fs,gain*s_,"short");
fclose(fs);
endfunction
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% codec2_demo.m
% Designed as an educational tool to explain the operation of Codec 2
% for conference and user group presentations on a projector. An
% alternative to static overhead slides.
%
% Derived from codec2-dev/octave/plamp.m
%
% usage:
% octave:1> plamp("../src/hts2a",40)
%
% Then press:
% c - to cycle through the wavform being displayed on the figure
% n - next frame
% b - back one frame
%
% tip: hold down n or b to animate the display
%
% The text files used as input are generated using c2sim:
%
% /codec2-dev/src$ c2sim ../raw/hts2a.raw --dump hts2a
%
% The Codec 2 README explains how to build c2sim with dump files
% enabled.
function codec2_demo(samname, f)
sn_name = strcat(samname,"_sn.txt");
Sn = load(sn_name);
sw_name = strcat(samname,"_sw.txt");
Sw = load(sw_name);
model_name = strcat(samname,"_model.txt");
model = load(model_name);
figure(1);
k = ' ';
wf = "Sn";
do
if strcmp(wf,"Sn")
clf;
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
plot(s);
axis([1 length(s) -20000 20000]);
end
if (strcmp(wf,"Sw"))
clf;
plot((0:255)*4000/256, Sw(f,:),";Sw;");
end
if strcmp(wf,"SwAm")
Wo = model(f,1);
L = model(f,2);
Am = model(f,3:(L+2));
plot((0:255)*4000/256, Sw(f,:),";Sw;");
hold on;
plot((1:L)*Wo*4000/pi, 20*log10(Am),"+;Am;r");
axis([1 4000 -10 80]);
hold off;
end
if strcmp(wf,"Am")
Wo = model(f,1);
L = model(f,2);
Am = model(f,3:(L+2));
plot((1:L)*Wo*4000/pi, 20*log10(Am),"+;Am;r");
axis([1 4000 -10 80]);
end
% interactive menu
printf("\rframe: %d menu: n-next b-back w-cycle window q-quit", f);
fflush(stdout);
k = kbhit();
if (k == 'n')
f = f + 1;
end
if (k == 'b')
f = f - 1;
end
if (k == 'w')
if strcmp(wf,"Sn")
next_wf = "Sw";
end
if strcmp(wf,"Sw")
next_wf = "SwAm";
end
if strcmp(wf,"SwAm")
next_wf = "Am";
end
if strcmp(wf,"Am")
next_wf = "Sn";
end
wf = next_wf;
end
until (k == 'q')
printf("\n");
endfunction
% cspec.m
% David Rowe Aug 2012
% Used to compare spectromgrams while experimenting with phase
function cspec(s1,s2)
f1 = fopen(s1,"rb");
s1 = fread(f1,Inf,"short");
f2 = fopen(s2,"rb");
s2 = fread(f2,Inf,"short");
Fs = 8000;
spec_win = 512;
state = 's1';
do
if strcmp(state,'s1')
spec(s1,Fs,spec_win);
%title(s1);
end
if strcmp(state,'s2')
spec(s2,Fs,spec_win);
%title(s2);
end
if strcmp(state,'diff')
spec(s1-s2,Fs,spec_win);
%title("difference");
end
printf("\rstate: %s space-toggle d-diff q-quit", state);
fflush(stdout);
k = kbhit();
if k == ' '
if strcmp(state,"diff")
next_state = 's1';
end
if strcmp(state,"s1")
next_state = 's2';
end
if strcmp(state,'s2')
next_state = 's1';
end
end
if k == 'd'
next_state = 'diff';
end
state = next_state;
until (k == 'q')
printf("\n");
endfunction
差异被折叠。
% fdmdv_demod.m
%
% Demodulator function for FDMDV modem (Octave version). Requires
% 8kHz sample rate raw files as input
%
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
function fdmdv_demod(rawfilename, nbits, pngname)
fdmdv; % include modem code
modulation = 'dqpsk';
fin = fopen(rawfilename, "rb");
gain = 1000;
frames = nbits/(Nc*Nb);
prev_rx_symbols = ones(Nc+1,1);
foff_phase = 1;
% BER stats
total_bit_errors = 0;
total_bits = 0;
bit_errors_log = [];
sync_log = [];
test_frame_sync_log = [];
test_frame_sync_state = 0;
% SNR states
sig_est = zeros(Nc+1,1);
noise_est = zeros(Nc+1,1);
% logs of various states for plotting
rx_symbols_log = [];
rx_timing_log = [];
foff_log = [];
rx_fdm_log = [];
snr_est_log = [];
% misc states
nin = M; % timing correction for sample rate differences
foff = 0;
track_log = [];
track = 0;
fest_state = 0;
% Main loop ----------------------------------------------------
for f=1:frames
% obtain nin samples of the test input signal
for i=1:nin
rx_fdm(i) = fread(fin, 1, "short")/gain;
end
rx_fdm_log = [rx_fdm_log rx_fdm(1:nin)];
% frequency offset estimation and correction
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, nin);
[foff_coarse S1 S2] = rx_est_freq_offset(rx_fdm, pilot, prev_pilot, nin);
if track == 0
foff = foff_coarse;
end
foff_log = [ foff_log foff ];
foff_rect = exp(j*2*pi*foff/Fs);
for i=1:nin
foff_phase *= foff_rect';
rx_fdm(i) = rx_fdm(i)*foff_phase;
end
% baseband processing
rx_baseband = fdm_downconvert(rx_fdm, nin);
rx_filt = rx_filter(rx_baseband, nin);
[rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, nin);
rx_timing_log = [rx_timing_log rx_timing];
nin = M;
if rx_timing > 2*M/P
nin += M/P;
end
if rx_timing < 0;
nin -= M/P;
end
if strcmp(modulation,'dqpsk')
rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
else
rx_symbols_log = [rx_symbols_log rx_symbols];
endif
[rx_bits sync f_err pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
[sig_est noise_est] = snr_update(sig_est, noise_est, pd);
snr_est = calc_snr(sig_est, noise_est);
snr_est_log = [snr_est_log snr_est];
foff -= 0.5*f_err;
prev_rx_symbols = rx_symbols;
sync_log = [sync_log sync];
% freq est state machine
[track fest_state] = freq_state(sync, fest_state);
track_log = [track_log track];
% count bit errors if we find a test frame
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
if (test_frame_sync == 1)
total_bit_errors = total_bit_errors + bit_errors;
total_bits = total_bits + Ntest_bits;
bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
else
bit_errors_log = [bit_errors_log 0];
end
% test frame sync state machine, just for more informative plots
next_test_frame_sync_state = test_frame_sync_state;
if (test_frame_sync_state == 0)
if (test_frame_sync == 1)
next_test_frame_sync_state = 1;
test_frame_count = 0;
end
end
if (test_frame_sync_state == 1)
% we only expect another test_frame_sync pulse every 4 symbols
test_frame_count++;
if (test_frame_count == 4)
test_frame_count = 0;
if ((test_frame_sync == 0))
next_test_frame_sync_state = 0;
end
end
end
test_frame_sync_state = next_test_frame_sync_state;
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
end
% ---------------------------------------------------------------------
% Print Stats
% ---------------------------------------------------------------------
ber = total_bit_errors / total_bits;
printf("%d bits %d errors BER: %1.4f\n",total_bits, total_bit_errors, ber);
% ---------------------------------------------------------------------
% Plots
% ---------------------------------------------------------------------
xt = (1:frames)/Rs;
secs = frames/Rs;
figure(1)
clf;
[n m] = size(rx_symbols_log);
plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
axis([-2 2 -2 2]);
title('Scatter Diagram');
figure(2)
clf;
subplot(211)
plot(xt, rx_timing_log)
title('timing offset (samples)');
subplot(212)
plot(xt, foff_log, '-;freq offset;')
hold on;
plot(xt, track_log*75, 'r;course-fine;');
hold off;
title('Freq offset (Hz)');
grid
figure(3)
clf;
subplot(211)
[a b] = size(rx_fdm_log);
xt1 = (1:b)/Fs;
plot(xt1, rx_fdm_log);
title('Rx FDM Signal');
subplot(212)
spec(rx_fdm_log,8000);
title('FDM Rx Spectrogram');
figure(4)
clf;
subplot(311)
stem(xt, sync_log)
axis([0 secs 0 1.5]);
title('BPSK Sync')
subplot(312)
stem(xt, bit_errors_log);
title('Bit Errors for test frames')
subplot(313)
plot(xt, test_frame_sync_log);
axis([0 secs 0 1.5]);
title('Test Frame Sync')
figure(5)
clf;
plot(xt, snr_est_log);
title('SNR Estimates')
endfunction
% fdmdv_demod_c.m
%
% Plots Octave dump file information from C FDMDV demodulator program,
% to give a similar set of plots to fdmdv_demod.m. Useful for off
% line analysis of demod performance.
%
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
function fdmdv_demod_c(dumpfilename, bits)
fdmdv; % include modem code
frames = bits/(Nc*Nb);
load(dumpfilename);
% BER stats
total_bit_errors = 0;
total_bits = 0;
bit_errors_log = [];
sync_log = [];
test_frame_sync_log = [];
test_frame_sync_state = 0;
% Run thru received bits to look for test pattern
bits_per_frame = Nc*Nb;
for f=1:frames
rx_bits = rx_bits_log_c((f-1)*bits_per_frame+1:f*bits_per_frame);
% count bit errors if we find a test frame
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
if (test_frame_sync == 1)
total_bit_errors = total_bit_errors + bit_errors;
total_bits = total_bits + Ntest_bits;
bit_errors_log = [bit_errors_log bit_errors/Ntest_bits];
else
bit_errors_log = [bit_errors_log 0];
end
% test frame sync state machine, just for more informative plots
next_test_frame_sync_state = test_frame_sync_state;
if (test_frame_sync_state == 0)
if (test_frame_sync == 1)
next_test_frame_sync_state = 1;
test_frame_count = 0;
end
end
if (test_frame_sync_state == 1)
% we only expect another test_frame_sync pulse every 4 symbols
test_frame_count++;
if (test_frame_count == 4)
test_frame_count = 0;
if ((test_frame_sync == 0))
next_test_frame_sync_state = 0;
end
end
end
test_frame_sync_state = next_test_frame_sync_state;
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
end
% ---------------------------------------------------------------------
% Plots
% ---------------------------------------------------------------------
xt = (1:frames)/Rs;
secs = frames/Rs;
figure(1)
clf;
plot(real(rx_symbols_log_c(1:Nc+1,15:frames)),imag(rx_symbols_log_c(1:Nc+1,15:frames)),'+')
axis([-2 2 -2 2]);
title('Scatter Diagram');
figure(2)
clf;
subplot(211)
plot(xt, rx_timing_log_c(1:frames))
title('timing offset (samples)');
subplot(212)
plot(xt, foff_log_c(1:frames), '-;freq offset;')
hold on;
plot(xt, coarse_fine_log_c(1:frames)*75, 'r;course-fine;');
hold off;
title('Freq offset (Hz)');
grid
figure(3)
clf;
subplot(211)
b = M*frames;
xt1 = (1:b)/Fs;
plot(xt1, rx_fdm_log_c(1:b));
title('Rx FDM Signal');
subplot(212)
spec(rx_fdm_log_c(1:b),8000);
title('FDM Rx Spectrogram');
figure(4)
clf;
subplot(311)
stem(xt, sync_bit_log_c(1:frames))
axis([0 secs 0 1.5]);
title('BPSK Sync')
subplot(312)
stem(xt, bit_errors_log);
title('Bit Errors for test frames')
subplot(313)
plot(xt, test_frame_sync_log);
axis([0 secs 0 1.5]);
title('Test Frame Sync')
figure(5)
clf;
plot(xt, snr_est_log_c(1:frames));
title('SNR Estimates')
endfunction
% fdmdv_mod.m
%
% Modulator function for FDMDV modem, uses test frames as input and
% outputs a raw file of 16 bit shorts at a sample rate of 8 kHz.
%
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
function tx_fdm = fdmdv_mod(rawfilename, nbits)
fdmdv; % include modem code
frames = floor(nbits/(Nc*Nb))
tx_fdm = [];
gain = 1000; % Scale up to 16 bit shorts
prev_tx_symbols = ones(Nc+1,1);
for i=1:frames
tx_bits = get_test_bits(Nc*Nb);
tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits,'dqpsk');
prev_tx_symbols = tx_symbols;
tx_baseband = tx_filter(tx_symbols);
tx_fdm = [tx_fdm real(fdm_upconvert(tx_baseband))];
end
tx_fdm *= gain;
fout = fopen(rawfilename,"wb");
fwrite(fout, tx_fdm, "short");
fclose(fout);
endfunction
% fdmdv_ut.m
%
% Unit Test program for FDMDV modem. Useful for general development as it has
% both tx and rx sides, and basic AWGN channel simulation.
%
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
fdmdv; % load modem code
% Simulation Parameters --------------------------------------
frames = 25;
EbNo_dB = 7.3;
Foff_hz = 0;
modulation = 'dqpsk';
hpa_clip = 150;
% ------------------------------------------------------------
tx_filt = zeros(Nc,M);
rx_symbols_log = [];
rx_phase_log = 0;
rx_timing_log = 0;
tx_pwr = 0;
noise_pwr = 0;
rx_fdm_log = [];
rx_baseband_log = [];
rx_bits_offset = zeros(Nc*Nb*2);
prev_tx_symbols = ones(Nc+1,1);
prev_rx_symbols = ones(Nc+1,1);
ferr = 0;
foff = 0;
foff_log = [];
tx_baseband_log = [];
tx_fdm_log = [];
% BER stats
total_bit_errors = 0;
total_bits = 0;
bit_errors_log = [];
sync_log = [];
test_frame_sync_log = [];
test_frame_sync_state = 0;
% SNR estimation states
sig_est = zeros(Nc+1,1);
noise_est = zeros(Nc+1,1);
% fixed delay simuation
Ndelay = M+20;
rx_fdm_delay = zeros(Ndelay,1);
% ---------------------------------------------------------------------
% Eb/No calculations. We need to work out Eb/No for each FDM carrier.
% Total power is sum of power in all FDM carriers
% ---------------------------------------------------------------------
C = 1; % power of each FDM carrier (energy/sample). Total Carrier power should = Nc*C = Nc
N = 1; % total noise power (energy/sample) of noise source across entire bandwidth
% Eb = Carrier power * symbol time / (bits/symbol)
% = C *(1/Rs) / 2
Eb_dB = 10*log10(C) - 10*log10(Rs) - 10*log10(2);
No_dBHz = Eb_dB - EbNo_dB;
% Noise power = Noise spectral density * bandwidth
% Noise power = Noise spectral density * Fs/2 for real signals
N_dB = No_dBHz + 10*log10(Fs/2);
Ngain_dB = N_dB - 10*log10(N);
Ngain = 10^(Ngain_dB/20);
% C/No = Carrier Power/noise spectral density
% = power per carrier*number of carriers / noise spectral density
CNo_dB = 10*log10(C) + 10*log10(Nc) - No_dBHz;
% SNR in equivalent 3000 Hz SSB channel
B = 3000;
SNR = CNo_dB - 10*log10(B);
% freq offset simulation states
phase_offset = 1;
freq_offset = exp(j*2*pi*Foff_hz/Fs);
foff_phase = 1;
t = 0;
foff = 0;
fest_state = 0;
track = 0;
track_log = [];
% ---------------------------------------------------------------------
% Main loop
% ---------------------------------------------------------------------
for f=1:frames
% -------------------
% Modulator
% -------------------
tx_bits = get_test_bits(Nc*Nb);
tx_symbols = bits_to_qpsk(prev_tx_symbols, tx_bits, modulation);
prev_tx_symbols = tx_symbols;
tx_baseband = tx_filter(tx_symbols);
tx_baseband_log = [tx_baseband_log tx_baseband];
tx_fdm = fdm_upconvert(tx_baseband);
tx_pwr = 0.9*tx_pwr + 0.1*real(tx_fdm)*real(tx_fdm)'/(M);
% -------------------
% Channel simulation
% -------------------
% frequency offset
%Foff_hz += 1/Rs;
Foff = Foff_hz;
for i=1:M
% Time varying freq offset
%Foff = Foff_hz + 100*sin(t*2*pi/(300*Fs));
%t++;
freq_offset = exp(j*2*pi*Foff/Fs);
phase_offset *= freq_offset;
tx_fdm(i) = phase_offset*tx_fdm(i);
end
tx_fdm = real(tx_fdm);
% HPA non-linearity
tx_fdm(find(abs(tx_fdm) > hpa_clip)) = hpa_clip;
tx_fdm_log = [tx_fdm_log tx_fdm];
rx_fdm = tx_fdm;
% AWGN noise
noise = Ngain*randn(1,M);
noise_pwr = 0.9*noise_pwr + 0.1*noise*noise'/M;
rx_fdm += noise;
rx_fdm_log = [rx_fdm_log rx_fdm];
% Delay
rx_fdm_delay(1:Ndelay-M) = rx_fdm_delay(M+1:Ndelay);
rx_fdm_delay(Ndelay-M+1:Ndelay) = rx_fdm;
%rx_fdm_delay = rx_fdm;
% -------------------
% Demodulator
% -------------------
% frequency offset estimation and correction, need to call rx_est_freq_offset even in track
% mode to keep states updated
[pilot prev_pilot pilot_lut_index prev_pilot_lut_index] = get_pilot(pilot_lut_index, prev_pilot_lut_index, M);
[foff_course S1 S2] = rx_est_freq_offset(rx_fdm_delay, pilot, prev_pilot, M);
if track == 0
foff = foff_course;
end
foff_log = [ foff_log foff ];
foff_rect = exp(j*2*pi*foff/Fs);
for i=1:M
foff_phase *= foff_rect';
rx_fdm_delay(i) = rx_fdm_delay(i)*foff_phase;
end
% baseband processing
rx_baseband = fdm_downconvert(rx_fdm_delay(1:M), M);
rx_baseband_log = [rx_baseband_log rx_baseband];
rx_filt = rx_filter(rx_baseband, M);
[rx_symbols rx_timing] = rx_est_timing(rx_filt, rx_baseband, M);
rx_timing_log = [rx_timing_log rx_timing];
%rx_phase = rx_est_phase(rx_symbols);
%rx_phase_log = [rx_phase_log rx_phase];
%rx_symbols = rx_symbols*exp(j*rx_phase);
[rx_bits sync foff_fine pd] = qpsk_to_bits(prev_rx_symbols, rx_symbols, modulation);
if strcmp(modulation,'dqpsk')
%rx_symbols_log = [rx_symbols_log rx_symbols.*conj(prev_rx_symbols)*exp(j*pi/4)];
rx_symbols_log = [rx_symbols_log pd];
else
rx_symbols_log = [rx_symbols_log rx_symbols];
endif
foff -= 0.5*ferr;
prev_rx_symbols = rx_symbols;
sync_log = [sync_log sync];
% freq est state machine
[track fest_state] = freq_state(sync, fest_state);
track_log = [track_log track];
% Update SNR est
[sig_est noise_est] = snr_update(sig_est, noise_est, pd);
% count bit errors if we find a test frame
% Allow 15 frames for filter memories to fill and time est to settle
[test_frame_sync bit_errors] = put_test_bits(rx_bits);
if test_frame_sync == 1
total_bit_errors = total_bit_errors + bit_errors;
total_bits = total_bits + Ntest_bits;
bit_errors_log = [bit_errors_log bit_errors];
else
bit_errors_log = [bit_errors_log 0];
end
% test frame sync state machine, just for more informative plots
next_test_frame_sync_state = test_frame_sync_state;
if (test_frame_sync_state == 0)
if (test_frame_sync == 1)
next_test_frame_sync_state = 1;
test_frame_count = 0;
end
end
if (test_frame_sync_state == 1)
% we only expect another test_frame_sync pulse every 4 symbols
test_frame_count++;
if (test_frame_count == 4)
test_frame_count = 0;
if ((test_frame_sync == 0))
next_test_frame_sync_state = 0;
end
end
end
test_frame_sync_state = next_test_frame_sync_state;
test_frame_sync_log = [test_frame_sync_log test_frame_sync_state];
end
% ---------------------------------------------------------------------
% Print Stats
% ---------------------------------------------------------------------
ber = total_bit_errors / total_bits;
% Peak to Average Power Ratio calcs from http://www.dsplog.com
papr = max(tx_fdm_log.*conj(tx_fdm_log)) / mean(tx_fdm_log.*conj(tx_fdm_log));
papr_dB = 10*log10(papr);
% Note Eb/No set point is for Nc data carriers only, exclduing pilot.
% This is convenient for testing BER versus Eb/No. Measured Eb/No
% includes power of pilot. Similar for SNR, first number is SNR excluding
% pilot pwr for Eb/No set point, 2nd value is measured SNR which will be a little
% higher as pilot power is included.
printf("Eb/No (meas): %2.2f (%2.2f) dB\n", EbNo_dB, 10*log10(0.25*tx_pwr*Fs/(Rs*Nc*noise_pwr)));
printf("bits........: %d\n", total_bits);
printf("errors......: %d\n", total_bit_errors);
printf("BER.........: %1.4f\n", ber);
printf("PAPR........: %1.2f dB\n", papr_dB);
printf("SNR...(meas): %2.2f (%2.2f) dB\n", SNR, calc_snr(sig_est, noise_est));
% ---------------------------------------------------------------------
% Plots
% ---------------------------------------------------------------------
figure(1)
clf;
[n m] = size(rx_symbols_log);
plot(real(rx_symbols_log(1:Nc+1,15:m)),imag(rx_symbols_log(1:Nc+1,15:m)),'+')
axis([-3 3 -3 3]);
title('Scatter Diagram');
figure(2)
clf;
subplot(211)
plot(rx_timing_log)
title('timing offset (samples)');
subplot(212)
plot(foff_log, '-;freq offset;')
hold on;
plot(track_log*75, 'r;course-fine;');
hold off;
title('Freq offset (Hz)');
figure(3)
clf;
subplot(211)
plot(real(tx_fdm_log));
title('FDM Tx Signal');
subplot(212)
Nfft=Fs;
S=fft(rx_fdm_log,Nfft);
SdB=20*log10(abs(S));
plot(SdB(1:Fs/4))
title('FDM Rx Spectrum');
figure(4)
clf;
subplot(311)
stem(sync_log)
axis([0 frames 0 1.5]);
title('BPSK Sync')
subplot(312)
stem(bit_errors_log);
title('Bit Errors for test frames')
subplot(313)
plot(test_frame_sync_log);
axis([0 frames 0 1.5]);
title('Test Frame Sync')
% gen_rn_coeffs.m
% David Rowe 13 april 2012
%
% Generate root raised cosine (Root Nyquist) filter coefficients
% thanks http://www.dsplog.com/db-install/wp-content/uploads/2008/05/raised_cosine_filter.m
function coeffs = gen_rn_coeffs(alpha, T, Rs, Nsym, M)
Ts = 1/Rs;
n = -Nsym*Ts/2:T:Nsym*Ts/2;
Nfilter = Nsym*M;
Nfiltertiming = M+Nfilter+M;
sincNum = sin(pi*n/Ts); % numerator of the sinc function
sincDen = (pi*n/Ts); % denominator of the sinc function
sincDenZero = find(abs(sincDen) < 10^-10);
sincOp = sincNum./sincDen;
sincOp(sincDenZero) = 1; % sin(pix/(pix) =1 for x =0
cosNum = cos(alpha*pi*n/Ts);
cosDen = (1-(2*alpha*n/Ts).^2);
cosDenZero = find(abs(cosDen)<10^-10);
cosOp = cosNum./cosDen;
cosOp(cosDenZero) = pi/4;
gt_alpha5 = sincOp.*cosOp;
Nfft = 4096;
GF_alpha5 = fft(gt_alpha5,Nfft)/M;
% sqrt causes stop band to be amplified, this hack pushes it down again
for i=1:Nfft
if (abs(GF_alpha5(i)) < 0.02)
GF_alpha5(i) *= 0.001;
endif
end
GF_alpha5_root = sqrt(abs(GF_alpha5)) .* exp(j*angle(GF_alpha5));
ifft_GF_alpha5_root = ifft(GF_alpha5_root);
coeffs = real((ifft_GF_alpha5_root(1:Nfilter)));
endfunction
% hp_filt.m
% David Rowe 20 Feb 2012
function hp_filt(in_file, out_file)
fin = fopen(in_file,"rb");
s = fread(fin,Inf,"short");
b = fir1(256, 300/4000, "high");
freqz(b);
s_hpf = filter(b,1,s);
fout = fopen(out_file,"wb");
fwrite(fout, s_hpf, "short");
endfunction
% lpcpf.m
% David Rowe Aug 27 2012
% Experiments with LPC post filtering
function lpcpf(ak_filename, f)
aks = load(ak_filename);
ak = aks(f,:);
[tmp p] = size(ak);
p -= 1;
A = freqz(1,ak, 4000);
AdB = 20*log10(abs(A));
gamma = 0.5;
gammas = gamma .^ (0:p);
W = freqz(ak .* gammas,1, 4000);
WdB = 20*log10(abs(W));
beta = 0.2;
R = abs(freqz(ak .* gammas, ak, 4000));
%P = (R/max(R)) .^ beta;
P = R .^ beta;
AP = abs(A) .* P;
eA = sum(abs(A) .^ 2);
eAP = sum(AP .^ 2);
gain = sqrt(eA/eAP)
AP *= gain;
PdB = 20*log10(P);
APdB = 20*log10(AP);
10*log10(sum(AP .^ 2))/10*log10(sum(abs(A) .^ 2))
figure(1);
clf;
plot(AdB);
hold on;
plot(WdB,'g');
plot(PdB,'r');
plot(APdB,'b.');
hold off;
endfunction
% lspwarp.m
% David Rowe Sep 2012
%
% Experimenting with non-linear LSP frequency axis for LSP quantisation
% Plots a scaled mel axis.
1;
function mel = freq2mel(f)
mel = 70*log10(1 + f/700);
endfunction
function freq = mel2freq(m)
freq = 700*(10 ^ (m/70) - 1);
endfunction
x = []; y = [];
for freq = 100:25:4000
mel = freq2mel(freq);
x = [x freq];
y = [y mel];
end
plot(x,y)
grid
mel_start = floor(freq2mel(100));
mel_end = floor(freq2mel(4000));
x = []; y = [];
for mel=mel_start:mel_end
freq = mel2freq(mel);
x = [x freq];
y = [y mel];
end
hold on;
plot(x,y, '+')
hold off;
% phasesecord.m
% David Rowe Aug 2012
% Used to experiment with aproximations of phase of 2nd order systems
function phasesecord(w,beta)
a = [1 -2*cos(w)*beta beta*beta];
b = 1;
[h w1] = freqz(b,a);
figure(1)
subplot(211)
plot(abs(h))
subplot(212)
plot(angle(h))
% for beta close to 1, we approximate 3 dB points as 1-beta above
% and below the resonance freq. Note this fails if w=0 as there is a
% double pole. Lets sample the freq response at the 3dB points and
% w:
ws = [w-(1-beta) w w+(1-beta)];
[h w1] = freqz(b,a,ws);
% gain as a fraction of max, should be 3dB. Within 1.3 dB or for w > pi/8,
% gets innacurate near w=0 due to 2nd pole
printf("mag measured...:"); printf("% 4.3f ", abs(h)/max(abs(h)));
% measured angle, 45 deg from angle at w
printf("\nangle measured.: "); printf("% 5.3f ", angle(h));
% Our estimate of angle, (pi+w) is phase at resonance, at lower 3dB
% phase is pi/4 ahead, at upper 3B pi/4 behind. -pi/2 is contribution of
% other pole at at -w to phase
ph_lower = (pi+w) + pi/4 - pi/2;
ph_res =(pi+w) - pi/2;
ph_upper = (pi+w) - pi/4 - pi/2;
ph_ests = [ph_lower ph_res ph_upper];
ph_ests = ph_ests - 2*pi*(floor(ph_ests/(2*pi)) + 0.5);
printf("\nangle estimated:"); printf("% 5.3f ", ph_ests);
printf("\n");
endfunction
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% Plot amplitude modelling information from dump files to test and develop
% LPC post filter.
function pllpcpf(samname, f)
% switch some stuff off to unclutter display
plot_Am = 0;
plot_Amq = 0;
plot_err = 0;
plot_lsp = 0;
plot_snr = 0;
plot_vsnr = 0;
plot_sw = 0;
plot_pw = 1;
plot_pwb = 1;
plot_rw = 1;
sn_name = strcat(samname,"_sn.txt");
Sn = load(sn_name);
sw_name = strcat(samname,"_sw.txt");
Sw = load(sw_name);
sw__name = strcat(samname,"_sw_.txt");
if (file_in_path(".",sw__name))
Sw_ = load(sw__name);
endif
model_name = strcat(samname,"_model.txt");
model = load(model_name);
modelq_name = strcat(samname,"_qmodel.txt");
if (file_in_path(".",modelq_name))
modelq = load(modelq_name);
endif
% Pw (LPC synth filter spectrum) before post filter
pwb_name = strcat(samname,"_pwb.txt");
if (file_in_path(".",pwb_name))
Pwb = load(pwb_name);
endif
% Rw (Post filter spectrum)
rw_name = strcat(samname,"_rw.txt");
if (file_in_path(".",rw_name))
Rw = load(rw_name);
endif
% Pw (LPC synth filter spectrum) after post filter
pw_name = strcat(samname,"_pw.txt");
if (file_in_path(".",pw_name))
Pw = load(pw_name);
endif
Ew_on = 1;
k = ' ';
do
figure(1);
clf;
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
size(s);
plot(s);
axis([1 length(s) -20000 20000]);
figure(2);
clf;
Wo = model(f,1);
L = model(f,2);
Am = model(f,3:(L+2));
if plot_Am
plot((1:L)*Wo*4000/pi, 20*log10(Am),";Am;r");
end
axis([1 4000 -10 80]);
hold on;
if plot_sw
plot((0:255)*4000/256, Sw(f,:),";Sw;");
end
if (file_in_path(".",modelq_name))
Amq = modelq(f,3:(L+2));
if plot_Amq
plot((1:L)*Wo*4000/pi, 20*log10(Amq),";Amq;g" );
end
if (file_in_path(".",pwb_name) && plot_pwb)
plot((0:255)*4000/256, 10*log10(Pwb(f,:)),";Pwb;r");
endif
if (file_in_path(".",rw_name) && plot_rw)
plot((0:255)*4000/256, 10*log10(Rw(f,:)),";Rw;b");
endif
if (file_in_path(".",pw_name) && plot_pw)
plot((0:255)*4000/256, 10*log10(Pw(f,:)),";Pw;g.");
endif
signal = Am * Am';
noise = (Am-Amq) * (Am-Amq)';
snr1 = 10*log10(signal/noise);
Am_err_label = sprintf(";Am error SNR %4.2f dB;m",snr1);
if plot_err
plot((1:L)*Wo*4000/pi, 20*log10(Amq) - 20*log10(Am), Am_err_label);
end
endif
hold off;
% interactive menu
printf("\rframe: %d menu: n-next b-back p-png q-quit", f);
fflush(stdout);
k = kbhit();
if (k == 'n')
f = f + 1;
endif
if (k == 'b')
f = f - 1;
endif
% optional print to PNG
if (k == 'p')
figure(1);
pngname = sprintf("%s_%d_sn.png",samname,f);
print(pngname, '-dpng', "-S500,500")
pngname = sprintf("%s_%d_sn_large.png",samname,f);
print(pngname, '-dpng', "-S800,600")
figure(2);
pngname = sprintf("%s_%d_sw.png",samname,f);
print(pngname, '-dpng', "-S500,500")
pngname = sprintf("%s_%d_sw_large.png",samname,f);
print(pngname, '-dpng', "-S1200,800")
endif
until (k == 'q')
printf("\n");
endfunction
% Copyright David Rowe 2010
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% Plots a bunch of information related to LSP quantisation:
% - speech file
% - LSPs before and after quantisation
% - SNR for each frame
%
% Note: there is a 160 sample (two frame delay) from the when a sample
% enters the input buffer until it is at the centre of the analysis window
function pllsp(rawfile,
dumpfile_prefix_lpc_only,
dumpfile_prefix_lsp,
start_f, end_f)
fs=fopen(rawfile,"rb");
s=fread(fs,Inf,"short");
lpc_snr_name = strcat(dumpfile_prefix_lpc_only,"_lpc_snr.txt");
lpc10_snr = load(lpc_snr_name);
lpc_snr_name = strcat(dumpfile_prefix_lsp,"_lpc_snr.txt");
lsp_snr = load(lpc_snr_name);
lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
lsps = load(lsp_name);
[m,n]=size(lsps);
lsp = lsps(1:2:m,:);
lsp_ = lsps(2:2:m,:);
figure(1);
clf;
subplot(211);
sp = s((start_f-2)*80:(end_f-2)*80);
plot(sp);
subplot(212);
plot(lpc10_snr((start_f+1):end_f)-lsp_snr((start_f+1):end_f));
figure(2);
plot((4000/pi)*lsp((start_f+1):end_f,:));
hold on;
plot((4000/pi)*lsp_((start_f+1):end_f,:),'+-');
hold off;
endfunction
% pllspdt.m
% Copyright David Rowe 2010
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% Test script to plot differences in LSps between frames
function pllspdt(rawfile,dumpfile_prefix_lsp,lspn, start_f, end_f)
fs=fopen(rawfile,"rb");
s=fread(fs,Inf,"short");
lsp_name = strcat(dumpfile_prefix_lsp,"_lsp.txt");
lsps = load(lsp_name);
[m,n]=size(lsps);
lsp = lsps(1:2:m,:);
lsp_ = lsps(2:2:m,:);
lspdt = lsp(2:m/2,:) - lsp(1:m/2-1,:);
figure(1);
clf;
sp = s((start_f-2)*80:(end_f-2)*80);
plot(sp);
figure(2);
plot((4000/pi)*lspdt((start_f+1):end_f,lspn));
endfunction
% Copyright David Rowe 2009
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% Plot two sparse phase prediction error text files.
% Generate data from print_pred_error, print_pred_error_sparse_wo_correction1 etc
function plppe(ppe1_file, ppe2_file, f)
ppe1 = load(ppe1_file);
ppe2 = load(ppe2_file);
std1 = std(nonzeros(ppe1(:,40:80)));
std2 = std(nonzeros(ppe2(:,40:80)));
printf("std dev for %s is %4.3f\n", ppe1_file, std1);
printf("std dev for %s is %4.3f\n", ppe2_file, std2);
figure(1);
clf;
subplot(211)
hist(nonzeros(ppe1(:,40:80)),20);
subplot(212)
hist(nonzeros(ppe2(:,40:80)),20);
k = ' ';
do
figure(2);
clf;
subplot(211)
L = length(nonzeros(ppe1(f,:)));
x = (1:L)*4000/L;
std1 = std(nonzeros(ppe1(f,:)));
legend = sprintf(";std dev %4.3f;", std1);
plot(x, nonzeros(ppe1(f,:)),legend);
axis([0 4000 -pi pi]);
subplot(212)
std2 = std(nonzeros(ppe2(f,:)));
legend = sprintf(";std dev %4.3f;", std2);
plot(x, nonzeros(ppe2(f,:)),legend);
axis([0 4000 -pi pi]);
% interactive menu
printf("\rframe: %d menu: n-next b-back p-png q-quit ", f);
fflush(stdout);
k = kbhit();
if (k == 'n')
f = f + 1;
endif
if (k == 'b')
f = f - 1;
endif
% optional print to PNG
if (k == 'p')
pngname = sprintf("%s_%d",samname,f);
png(pngname);
endif
until (k == 'q')
printf("\n");
endfunction
% Copyright David Rowe 2010
% This program is distributed under the terms of the GNU General Public License
% Version 2
% plots the difference of two files
function plsub(samname1, samname2, start_sam, end_sam, pngname)
fs1=fopen(samname1,"rb");
s1=fread(fs1,Inf,"short");
fs2=fopen(samname2,"rb");
s2=fread(fs2,Inf,"short");
st = 1;
en = length(s1);
if (nargin >= 3)
st = start_sam;
endif
if (nargin >= 4)
en = end_sam;
endif
figure(1);
clf;
l1 = strcat("r;",samname1,";");
plot(s1(st:en) - s2(st:en), l1);
%axis([1 en-st min(s1(st:en)) max(s1(st:en))]);
if (nargin == 5)
pngname = sprintf("%s.png",pngname);
print(pngname, '-dpng', "-S500,500")
pngname = sprintf("%s_large.png",pngname);
print(pngname, '-dpng', "-S800,600")
endif
endfunction
% Copyright David Rowe 2009
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
% Plot voicing information from sample and dump files.
%
% samfilename is the raw source file, e.g. "../raw/hts1a.raw"
% samname is the dumpfile prefix, e.g. "../src/hts1a"
%
% There is a 160 sample (two frame delay) from the when a sample
% enters the input buffer until it is at the centre of the analysis window
function plvoicing(samfilename, samname, start_f, end_f, pngname)
fs=fopen(samfilename,"rb");
s=fread(fs,Inf,"short");
snr_name = strcat(samname,"_snr.txt");
snr = load(snr_name);
model_name = strcat(samname,"_model.txt");
model = load(model_name);
Wo = model((start_f+1):end_f,1);
F0 = Wo*4000/pi;
dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
% work out LP and HP energy
for f=(start_f+1):end_f
L = model(f,2);
Am = model(f,3:(L+2));
L2 = floor(L/2);
elow = Am(1:L2) * Am(1:L2)';
ehigh = Am(L2:L) * Am(L2:L)';
erat(f-(start_f+1)+1) = 10*log10(elow/ehigh);
endfor
figure(1);
clf;
sp = s((start_f-2)*80:(end_f-2)*80);
plot(sp);
hold on;
vhigh = snr((start_f+1):end_f) > 7;
vlow = snr((start_f+1):end_f) > 4;
% test correction based on erat
vlowadj = vlow;
for f=1:length(erat)-1
if (vlow(f) == 0)
if (erat(f) > 10)
vlowadj(f) = 1;
endif
endif
if (vlow(f) == 1)
if (erat(f) < -10)
vlowadj(f) = 0;
endif
if (abs(dF0(f)) > 15)
vlowadj(f) = 0;
endif
endif
endfor
x = 1:(end_f-start_f);
plot(x*80,snr((start_f+1):end_f)*1000,';SNRdB x 1000;g+');
plot(x*80,-8000 + vhigh*2000,';7dB thresh;g');
plot(x*80,-11000 + vlowadj*2000,';vlow with corr;g');
plot(x*80,erat*1000,';elow/ehigh in dB;r');
plot(x*80,-14000 + vlow*2000,';4dB thresh;r');
hold off;
grid
if (nargin == 5)
print(pngname, "-dpng", "-S500,500")
endif
figure(2)
Wo = model((start_f+1):end_f,1);
F0 = Wo*4000/pi;
dF0 = F0(1:length(Wo)-1) - F0(2:length(Wo));
%plot(dF0,'+--')
%hold on;
%plot([ 1 length(dF0) ], [10 10] ,'r')
%plot([ 1 length(dF0) ], [-10 -10] ,'r')
%axis([1 length(dF0) -50 50])
%hold off;
plot(F0,'+--')
endfunction
% sd.m
% David Rowe Aug 2012
% Plots the spectal distorion between twofiles of LPCs. Used for LSP
% quantisation tuning.
function sd(raw_filename, dump_file_prefix, f)
ak1_filename = sprintf("%s_ak.txt", dump_file_prefix);
ak2_filename = sprintf("%s_ak_.txt", dump_file_prefix);
ak1 = load(ak1_filename);
ak2 = load(ak2_filename);
[ak1_r, ak1_c] = size(ak1);
[ak2_r, ak2_c] = size(ak1);
frames = max([ak1_r ak2_r]);
sd = zeros(1,frames);
Ndft = 512;
A1 = zeros(frames, Ndft);
A2 = zeros(frames, Ndft);
% initial helicopter view of all frames
for i = 1:frames
A1(i,:) = -20*log10(abs(fft(ak1(i,:),Ndft)));
A2(i,:) = -20*log10(abs(fft(ak2(i,:),Ndft)));
sd(i) = sum((A1(i,:) - A2(i,:)).^2)/Ndft;
end
printf("sd av %3.2f dB*dB\n", sum(sd)/frames);
figure(1);
clf;
subplot(211)
fs=fopen(raw_filename,"rb");
s = fread(fs,Inf,"short");
plot(s);
subplot(212)
plot(sd);
% now enter single step mode so we can analyse each frame
sn_name = strcat(dump_file_prefix,"_sn.txt");
Sn = load(sn_name);
lsp1_filename = sprintf("%s_lsp.txt", dump_file_prefix);
lsp2_filename = sprintf("%s_lsp_.txt", dump_file_prefix);
lsp1 = load(lsp1_filename);
lsp2 = load(lsp2_filename);
weights_filename = sprintf("%s_weights.txt", dump_file_prefix);
if file_in_path(".",weights_filename)
weights = load(weights_filename);
end
k = ' ';
do
figure(2);
clf;
subplot(211)
s = [ Sn(2*f-1,:) Sn(2*f,:) ];
size(s);
plot(s);
axis([1 length(s) -20000 20000]);
subplot(212);
plot((1:Ndft/2)*4000/(Ndft/2), A1(f,1:(Ndft/2)),";A1;r");
axis([1 4000 -20 40]);
hold on;
plot((1:Ndft/2)*4000/(Ndft/2), A2(f,1:(Ndft/2)),";A2;");
if file_in_path(".",weights_filename)
plot(lsp1(f,:)*4000/pi, weights(f,:),";weights;g+");
end
for l=1:10
plot([lsp1(f,l)*4000/pi lsp1(f,l)*4000/pi], [0 -10], 'r');
plot([lsp2(f,l)*4000/pi lsp2(f,l)*4000/pi], [-10 -20], 'b');
endfor
plot(0,0,';lsp1;r');
plot(0,0,';lsp2;b');
sd_str = sprintf(";sd %3.2f dB*dB;", sd(f));
plot(0,0,sd_str);
hold off;
% interactive menu
printf("\rframe: %d menu: n-next b-back q-quit", f);
fflush(stdout);
k = kbhit();
if (k == 'n')
f = f + 1;
endif
if (k == 'b')
f = f - 1;
endif
until (k == 'q')
printf("\n");
endfunction
% spec.m
% Jean Marc Valin
%
% Spectrogram function for Octave
%
% Copyright (c) John-Marc Valin 2012
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions
% are met:
%
% - Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
%
% - Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in the
% documentation and/or other materials provided with the distribution.
%
% - Neither the name of Jean Marc Valin nor the names of its
% contributors may be used to endorse or promote products derived from
% this software without specific prior written permission.
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
% ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
% LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
% A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
% CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
% EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
% PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
% PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
% LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
% NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
% SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
function X = spec(x, Fs, framesize, start, stop)
gr=[zeros(1024,1),[0:1023]'/1023,.68*[0:1023]'/1023];
%gr=[.4*[0:1023]'/1023,[0:1023]'/1023,.68*[0:1023]'/1023];
%t=[0:1023]'/1023;
%t=(1+.25*t-cos(pi*t))/2.25;
%gr = [zeros(1024,1),t,.68*t];
%colormap(gr);
if nargin < 2 || isempty(Fs)
Fs = 44100;
end
if nargin < 3 || isempty(framesize)
framesize = 2048;
endif
offset = framesize/4;
X = 20*log10(abs(specgram(x, framesize, 48000, blackmanharris(framesize)', framesize-offset)));
XM=max(max(X));
X = max(XM-120,X);
%size(X)
F = -[framesize/2-1:-1:0]/framesize*Fs;
%F = [0:127]/128*24000;
T=[1:size(X,2)]/Fs*offset;
%imagesc(X(end:-1:1,:));
if nargin < 4 || isempty(start)
istart=1;
else
istart = round(start*Fs/offset);
end
if nargin < 5 || isempty(stop)
istop = size(X,2);
else
istop = round(stop*Fs/offset);
endif
istart = max(1,istart);
istop = min(istop, size(X,2));
imagesc(T(1+istart:istop), F, X(end:-1:1,1+istart:istop));
X = X(:,1+istart:istop);
差异被折叠。
% tget-spec.m
%
% Used in conjunction with src/fdmdv_demod to test the
% fdmdv_get_rx_spectrum() function.
%
% codec2-dev/src$ ./fdmdv_demod fdmdv_mod.raw tmp.c2 dump.txt
% octave:3> tget_spec("../src/dump.txt")
%
% Copyright David Rowe 2012
% This program is distributed under the terms of the GNU General Public License
% Version 2
%
function tfft_log(dumpfilename)
load(dumpfilename);
[rows cols] = size(rx_spec_log_c);
Fs = 8000; low_freq = 0; high_freq = 2500;
res = (Fs/2)/cols;
st_bin = low_freq/res + 1;
en_bin = high_freq/res;
xaxis = (st_bin:en_bin)*res;
f_start = 2; f_end = 100;
beta = 0.1;
av = zeros(f_end, en_bin-st_bin+1);
for r=f_start:f_end
x = (1-beta)*av(r-1,:) + beta*rx_spec_log_c(r,st_bin:en_bin);
av(r,:) = x;
end
% spectrogram (waterfall)
figure(1)
clf;
imagesc(av,[-40 0]);
% animated spectrum display
figure(2)
clf;
for r=f_start:f_end
plot(xaxis, av(r,:))
axis([ low_freq high_freq -40 0])
sleep(0.1)
end
endfunction
% twotone.m
% David Rowe Aug 2012
% Used to experiment with combining phase of two tones
function cbphase
Wo = 100.0*pi/4000;
L = floor(pi/Wo);
phi = zeros(1,L);
% two harmonics
a = 20; b = 21;
% set up phases to whatever
phi(a) = -pi;
phi(b) = -pi/2;
% synthesis the two-tone signal
N = 16000;
Nplot = 250;
s = zeros(1,N);
for m=a:b
s_m = cos(m*Wo*(0:(N-1)) + phi(m));
s = s + s_m;
endfor
% now our theory says that this signal should be the same perceptually
phi_(a) = (phi(a) - phi(b))/2;
phi_(b) = (phi(b) - phi(a))/2;
s_ = zeros(1,N);
for m=a:b
s_m = cos(m*Wo*(0:(N-1)) + phi_(m));
s_ = s_ + s_m;
endfor
% plot them and see if envelope has the same phase, but "carriers"
% have different phase
figure(1);
clf;
subplot(211);
plot(s(1:Nplot));
subplot(212);
plot(s_(1:Nplot),'r');
endfunction
% twotone1.m
% David Rowe Aug 17 2012
%
% Used to experiment with combining phase of two tones. This version
% sets up a complete synthetic speech signal then tries to combine the
% phase of high frequency tones. Lets see if we can do this and keep perceptual
% nature of signal the same.
function twotone1
% hts1a frame 47
Wo = 0.093168;
L = 33;
%A = [69.626907 460.218536 839.677429 2577.498047 972.647888 712.755066 489.048553 364.830536 409.230652 371.767487 489.112854 893.127014 2447.596680 752.878113 475.720520 234.452271 248.161606 232.171051 202.669891 323.914490 678.749451 362.958038 211.652512 170.764435 148.631790 169.261673 272.254150 176.872375 67.344391 99.022301 60.812035 34.319073 14.864757];
A = zeros(1,L)*100;
phi = [1.560274 1.508063 -1.565184 1.289117 -2.547365 1.412528 -1.303992 3.121130 1.087573 -1.158161 -2.928007 0.995093 -2.614023 0.246136 -2.267406 2.143802 -0.273431 -2.266897 1.685171 -0.668712 2.699722 -1.151891 2.406379 -0.046192 -2.718611 0.761067 -2.305014 0.133172 -1.428978 1.492630 -1.668385 1.539734 -1.336615];
%phi = zeros(1,L);
st = floor(L/2);
%st = 1;
A(st:st+5) = 1000;
% now set up phase of signal with phase of upper frequency harmonic
% pairs combined
phi_ = phi;
for m=floor(L/2):2:L
phi_(m) = (phi(m) - phi(m+1))/2;
phi_(m+1) = (phi(m+1) - phi(m))/2;
%phi_(m+1) = 0;
end
% synthesise the signals
N = 16000;
Nplot = 250;
s = zeros(1,N);
for m=st:L
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi(m));
s = s + s_m;
endfor
s_ = zeros(1,N);
for m=st:L
s_m = A(m)*cos(m*Wo*(0:(N-1)) + phi_(m));
s_ = s_ + s_m;
endfor
% plot them, expect to see similar time domain waveforms
figure(1);
clf;
subplot(211);
plot(s(1:Nplot));
subplot(212);
plot(s_(1:Nplot),'r');
figure(2);
clf;
subplot(211);
plot(s(1:Nplot)-s_(1:Nplot));
% save to disk
gain = 1;
fs=fopen("twotone1_orig.raw","wb");
fwrite(fs,gain*s,"short");
fclose(fs);
fs=fopen("twotone1_comb.raw","wb");
fwrite(fs,gain*s_,"short");
fclose(fs);
endfunction
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论