#a
option(BUILD_SHARED_LIBS
"Build shared library. Set to OFF for static library." ON)
-option(UNITTEST "Build unittest binaries." OFF)
+option(UNITTEST "Build unittest binaries." ON)
option(INSTALL_EXAMPLES "Install example code." OFF)
if(INSTALL_EXAMPLES)
install(DIRECTORY octave raw script voicing wav
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 -
+ $ ./fdmdv_get_test_bits - 14000 | ./fdmdv_mod - - | ./fdmdv_demod - - 14 demod_dump.txt | ./fdmdv_put_test_bits -
Use Octave to look at plots of 1 second (1400 bits) of modem operation:
+++ /dev/null
-# 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
+++ /dev/null
-/*
- fl_fdmdv.cxx
- Created 14 June 2012
- David Rowe
-
- Fltk 1.3 based GUI program to prototype FDMDV & Codec 2 integration
- issues such as:
-
- + spectrum, waterfall, and other FDMDV GUI displays
- + integration with real time audio I/O using portaudio
- + what we do with audio when out of sync
-*/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <unistd.h>
-
-#include <FL/Fl.H>
-#include <FL/Fl_Window.H>
-#include <FL/Fl_Box.H>
-#include <FL/fl_draw.H>
-#include <FL/Fl_Group.H>
-#include <FL/names.h>
-
-#include "portaudio.h"
-
-#include "fdmdv.h"
-#include "codec2.h"
-
-#define MIN_DB -40.0
-#define MAX_DB 0.0
-#define BETA 0.1 // constant for time averageing spectrum data
-#define MIN_HZ 0
-#define MAX_HZ 4000
-#define WATERFALL_SECS_Y 5 // number of seconds respresented by y axis of waterfall
-#define DT 0.02 // time between samples
-#define FS 8000 // FDMDV modem sample rate
-
-#define SCATTER_MEM (FDMDV_NSYM)*50
-#define SCATTER_X_MAX 3.0
-#define SCATTER_Y_MAX 3.0
-
-// main window params
-
-#define W 1200
-#define W3 (W/3)
-#define H 600
-#define H2 (H/2)
-#define SP 20
-
-// sound card
-
-#define SAMPLE_RATE 48000 /* 48 kHz sampling rate rec. as we
- can trust accuracy of sound
- card */
-#define N8 FDMDV_NOM_SAMPLES_PER_FRAME /* processing buffer size at 8 kHz */
-#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
-#define N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
-#define NUM_CHANNELS 2 /* I think most sound cards prefer stereo,
- we will convert to mono */
-
-#define BITS_PER_CODEC_FRAME (2*FDMDV_BITS_PER_FRAME)
-#define BYTES_PER_CODEC_FRAME (BITS_PER_CODEC_FRAME/8)
-
-// forward class declarations
-
-class Spectrum;
-class Waterfall;
-class Scatter;
-class Scalar;
-
-// Globals --------------------------------------
-
-char *fin_name = NULL;
-char *fout_name = NULL;
-char *sound_dev_name = NULL;
-FILE *fin = NULL;
-FILE *fout = NULL;
-struct FDMDV *fdmdv;
-struct CODEC2 *codec2;
-float av_mag[FDMDV_NSPEC]; // shared between a few classes
-
-// GUI variables --------------------------------
-
-Fl_Group *agroup;
-Fl_Window *window;
-Fl_Window *zoomSpectrumWindow = NULL;
-Fl_Window *zoomWaterfallWindow = NULL;
-Spectrum *aSpectrum;
-Spectrum *aZoomedSpectrum;
-Waterfall *aWaterfall;
-Waterfall *aZoomedWaterfall;
-Scatter *aScatter;
-Scalar *aTimingEst;
-Scalar *aFreqEst;
-Scalar *aSNR;
-int zoom_spectrum = 0;
-
-// Main processing loop states ------------------
-
-float Ts = 0.0;
-short input_buf[2*FDMDV_NOM_SAMPLES_PER_FRAME];
-int n_input_buf = 0;
-int nin = FDMDV_NOM_SAMPLES_PER_FRAME;
-short *output_buf;
-int n_output_buf = 0;
-int codec_bits[2*FDMDV_BITS_PER_FRAME];
-int state = 0;
-
-// Portaudio states -----------------------------
-
-PaStream *stream = NULL;
-PaError err;
-
-typedef struct {
- float in48k[FDMDV_OS_TAPS + N48];
- float in8k[MEM8 + N8];
-} paCallBackData;
-
-// Class for each window type ------------------
-
-class Spectrum: public Fl_Box {
-protected:
- int handle(int event) {
-
- // detect a left mouse down if inside the spectrum window
-
- if ((event == FL_NO_EVENT) && (Fl::event_button() == 1)) {
- if ((Fl::event_x() > x()) && (Fl::event_x() < (x() + w())) &&
- (Fl::event_y() > y()) && (Fl::event_y() < (y() + h()))) {
-
- // show zoomed spectrum window
-
- zoomSpectrumWindow->show();
- }
-
- }
- return 0;
- }
-
- void draw() {
- float x_px_per_point = 0.0;
- float y_px_per_dB = 0.0;
- int i, x1, y1, x2, y2;
- float mag1, mag2;
- char label[20];
- float px_per_hz;
-
- Fl_Box::draw();
- fl_color(FL_BLACK);
- fl_rectf(x(),y(),w(),h());
- fl_color(FL_GREEN);
- fl_line_style(FL_SOLID);
-
- fl_push_clip(x(),y(),w(),h());
- //printf("%d %d\n", w(), h());
- x_px_per_point = (float)w()/FDMDV_NSPEC;
- y_px_per_dB = (float)h()/(MAX_DB - MIN_DB);
-
- // plot spectrum
-
- for(i=0; i<FDMDV_NSPEC-1; i++) {
- mag1 = av_mag[i];
- mag2 = av_mag[i+1];
-
- x1 = x() + i*x_px_per_point;
- y1 = y() + -mag1*y_px_per_dB;
- x2 = x() + (i+1)*x_px_per_point;
- y2 = y() + -mag2*y_px_per_dB;
- fl_line(x1,y1,x2,y2);
- }
-
- // y axis graticule
-
- fl_line_style(FL_DOT);
- for(i=MIN_DB; i<MAX_DB; i+=10) {
- x1 = x();
- y1 = y() + -i*y_px_per_dB;
- x2 = x() + w();
- y2 = y1;
- //printf("%d %d %d %d\n", x1, y1, x2, y2);
- fl_line(x1,y1,x2,y2);
- sprintf(label, "%d", i);
- fl_draw(label, x1, y1);
- }
-
- // x axis graticule
-
- px_per_hz = (float)w()/(MAX_HZ-MIN_HZ);
- fl_line_style(FL_DOT);
- for(i=500; i<MAX_HZ; i+=500) {
- x1 = x() + i*px_per_hz;
- y1 = y();
- x2 = x1;
- y2 = y() + h();
- //printf("i=%d %d %d %d %d\n", i, x1, y1, x2, y2);
- fl_line(x1,y1,x2,y2);
- sprintf(label, "%d", i);
- fl_draw(label, x1, y2);
- }
-
- fl_pop_clip();
- }
-
-public:
- Spectrum(int x, int y, int w, int h): Fl_Box(x, y, w, h, "Spectrum")
- {
- align(FL_ALIGN_TOP);
- labelsize(10);
- };
-
-};
-
-
-/*
-
- Notes:
-
- The height h() pixels represents WATERFALL_SECS_Y of data. Every DT
- seconds we get a vector of FDMDV_NSPEC spectrum samples which we use
- to update the last row. The height of each row is dy pixels, which
- maps to DT seconds. We call each dy high rectangle of pixels a
- block.
-
-*/
-
-class Waterfall: public Fl_Box {
-protected:
-
- int prev_w, prev_h;
- unsigned *pixel_buf;
- unsigned heatmap_lut[256];
- int greyscale;
-
- void new_pixel_buf(int w, int h) {
- int buf_sz, i;
-
- prev_w = w; prev_h = h;
- buf_sz = h*w;
- pixel_buf = new unsigned[buf_sz];
- for(i=0; i<buf_sz; i++)
- pixel_buf[i] = 0;
- }
-
- int handle(int event) {
-
- // detect a left mouse down if inside the window
-
- if ((event == FL_NO_EVENT) && (Fl::event_button() == 1)) {
- if ((Fl::event_x() > x()) && (Fl::event_x() < (x() + w())) &&
- (Fl::event_y() > y()) && (Fl::event_y() < (y() + h()))) {
-
- // show zoomed spectrum window
-
- zoomWaterfallWindow->show();
- }
-
- }
- return 0;
- }
-
- // map val to a rgb colour
- // from http://eddiema.ca/2011/01/21/c-sharp-heatmaps/
-
- unsigned heatmap(float val, float min, float max) {
- unsigned r = 0;
- unsigned g = 0;
- unsigned b = 0;
-
- val = (val - min) / (max - min);
- if(val <= 0.2) {
- b = (unsigned)((val / 0.2) * 255);
- } else if(val > 0.2 && val <= 0.7) {
- b = (unsigned)((1.0 - ((val - 0.2) / 0.5)) * 255);
- }
- if(val >= 0.2 && val <= 0.6) {
- g = (unsigned)(((val - 0.2) / 0.4) * 255);
- } else if(val > 0.6 && val <= 0.9) {
- g = (unsigned)((1.0 - ((val - 0.6) / 0.3)) * 255);
- }
- if(val >= 0.5) {
- r = (unsigned)(((val - 0.5) / 0.5) * 255);
- }
-
- //printf("%f %x %x %x\n", val, r, g, b);
-
- return (b << 16) + (g << 8) + r;
- }
-
- void draw() {
- float spec_index_per_px, intensity_per_dB;
- int px_per_sec;
- int index, dy, dy_blocks, bytes_in_row_of_blocks, b;
- int px, py, intensity;
- unsigned *last_row, *pdest, *psrc;
-
- /* detect resizing of window */
-
- if ((h() != prev_h) || (w() != prev_w)) {
- delete pixel_buf;
- new_pixel_buf(w(), h());
- }
-
- Fl_Box::draw();
-
- // determine dy, the height of one "block"
-
- px_per_sec = (float)h()/WATERFALL_SECS_Y;
- dy = DT*px_per_sec;
-
- // number of dy high blocks in spectrogram
-
- dy_blocks = h()/dy;
-
- // shift previous bit map
-
- bytes_in_row_of_blocks = dy*w()*sizeof(unsigned);
-
- for(b=0; b<dy_blocks-1; b++) {
- pdest = pixel_buf + b*w()*dy;
- psrc = pixel_buf + (b+1)*w()*dy;
- memcpy(pdest, psrc, bytes_in_row_of_blocks);
- }
-
- // create a new row of blocks at bottom
-
- spec_index_per_px = (float)FDMDV_NSPEC/(float)w();
- intensity_per_dB = (float)256/(MAX_DB - MIN_DB);
- last_row = pixel_buf + dy*(dy_blocks - 1)*w();
-
- for(px=0; px<w(); px++) {
- index = px*spec_index_per_px;
- intensity = intensity_per_dB * (av_mag[index] - MIN_DB);
- if (intensity > 255) intensity = 255;
- if (intensity < 0) intensity = 0;
-
- if (greyscale) {
- for(py=0; py<dy; py++)
- last_row[px+py*w()] = intensity<<8;
- }
- else {
- for(py=0; py<dy; py++)
- last_row[px+py*w()] = heatmap_lut[intensity];
- }
- }
-
- // update bit map
-
- fl_draw_image((uchar*)pixel_buf, x(), y(), w(), h(), 4, 0);
-
- }
-
-public:
-
- Waterfall(int x, int y, int w, int h): Fl_Box(x, y, w, h, "Waterfall")
- {
- int i;
-
- for(i=0; i<255; i++) {
- heatmap_lut[i] = heatmap((float)i, 0.0, 255.0);
- }
- greyscale = 0;
-
- align(FL_ALIGN_TOP);
- labelsize(10);
- new_pixel_buf(w,h);
- };
-
- ~Waterfall() {
- delete pixel_buf;
- }
-};
-
-
-class Scatter: public Fl_Box {
-protected:
- COMP mem[SCATTER_MEM];
- COMP new_samples[FDMDV_NSYM];
- int prev_w, prev_h, prev_x, prev_y;
-
- void draw() {
- float x_scale;
- float y_scale;
- int i, j, x1, y1;
-
- Fl_Box::draw();
-
- /* detect resizing of window */
-
- if ((h() != prev_h) || (w() != prev_w) || (x() != prev_x) || (y() != prev_y)) {
- fl_color(FL_BLACK);
- fl_rectf(x(),y(),w(),h());
- prev_h = h(); prev_w = w(); prev_x = x(); prev_y = y();
- }
-
- fl_push_clip(x(),y(),w(),h());
-
- x_scale = w()/SCATTER_X_MAX;
- y_scale = h()/SCATTER_Y_MAX;
-
- // erase last samples
-
- fl_color(FL_BLACK);
- for(i=0; i<FDMDV_NSYM; i++) {
- x1 = x_scale * mem[i].real + x() + w()/2;
- y1 = y_scale * mem[i].imag + y() + h()/2;
- fl_point(x1, y1);
- mem[i] = mem[i+FDMDV_NSYM];
- }
-
- // shift memory
-
- for(i=FDMDV_NSYM; i<SCATTER_MEM-FDMDV_NSYM; i++) {
- mem[i] = mem[i+FDMDV_NSYM];
- }
-
- // draw new samples
-
- fl_color(FL_GREEN);
- for(i=SCATTER_MEM-FDMDV_NSYM, j=0; i<SCATTER_MEM; i++,j++) {
- x1 = x_scale * new_samples[j].real + x() + w()/2;
- y1 = y_scale * new_samples[j].imag + y() + h()/2;
- fl_point(x1, y1);
- mem[i] = new_samples[j];
- }
- fl_pop_clip();
- }
-
-public:
- Scatter(int x, int y, int w, int h): Fl_Box(x, y, w, h, "Scatter")
- {
- int i;
-
- align(FL_ALIGN_TOP);
- labelsize(10);
-
- for(i=0; i<SCATTER_MEM; i++) {
- mem[i].real = 0.0;
- mem[i].imag = 0.0;
- }
-
- prev_w = 0; prev_h = 0; prev_x = 0; prev_y = 0;
- };
-
- void add_new_samples(COMP samples[]) {
- int i;
-
- for(i=0; i<FDMDV_NSYM; i++)
- new_samples[i] = samples[i];
- }
-
-};
-
-
-// general purpose way of plotting scalar values that are
-// updated once per frame
-
-class Scalar: public Fl_Box {
-protected:
- int x_max, y_max;
- float *mem; /* array of x_max samples */
- float new_sample;
- int index, step;
- int prev_w, prev_h, prev_x, prev_y;
-
- int clip(int y1) {
- if (y1 > (h()/2 - 10))
- y1 = h()/2 - 10;
- if (y1 < -(h()/2 - 10))
- y1 = -(h()/2 - 10);
- return y1;
- }
-
- void draw() {
- float x_scale;
- float y_scale;
- int i, x1, y1, x2, y2;
- char label[100];
-
- Fl_Box::draw();
-
- /* detect resizing of window */
-
- if ((h() != prev_h) || (w() != prev_w) || (x() != prev_x) || (y() != prev_y)) {
- fl_color(FL_BLACK);
- fl_rectf(x(),y(),w(),h());
- prev_h = h(); prev_w = w(); prev_x = x(); prev_y = y();
- }
-
- fl_push_clip(x(),y(),w(),h());
-
- x_scale = (float)w()/x_max;
- y_scale = (float)h()/(2.0*y_max);
-
- // erase last sample
-
- fl_color(FL_BLACK);
- x1 = x_scale * index + x();
- y1 = y_scale * mem[index];
- y1 = clip(y1);
- y1 = y() + h()/2 - y1;
- fl_point(x1, y1);
-
- // draw new sample
-
- fl_color(FL_GREEN);
- x1 = x_scale * index + x();
- y1 = y_scale * new_sample;
- y1 = clip(y1);
- y1 = y() + h()/2 - y1;
- fl_point(x1, y1);
- mem[index] = new_sample;
-
- index++;
- if (index >= x_max)
- index = 0;
-
- // y axis graticule
-
- step = 10;
-
- while ((2.0*y_max/step) > 10)
- step *= 2.0;
- while ((2.0*y_max/step) < 4)
- step /= 2.0;
-
- fl_color(FL_DARK_GREEN);
- fl_line_style(FL_DOT);
- for(i=-y_max; i<y_max; i+=step) {
- x1 = x();
- y1 = y() + h()/2 - i*y_scale;
- x2 = x() + w();
- y2 = y1;
- fl_line(x1,y1,x2,y2);
- }
-
- // y axis graticule labels
-
- fl_color(FL_GREEN);
- fl_line_style(FL_SOLID);
- for(i=-y_max; i<y_max; i+=step) {
- x1 = x();
- y1 = y() + h()/2 - i*y_scale;
- sprintf(label, "%d", i);
- fl_draw(label, x1, y1);
- }
- fl_pop_clip();
- }
-
-public:
- Scalar(int x, int y, int w, int h, int x_max_, int y_max_, const char name[]): Fl_Box(x, y, w, h, name)
- {
- int i;
-
- align(FL_ALIGN_TOP);
- labelsize(10);
-
- x_max = x_max_; y_max = y_max_;
- mem = new float[x_max];
- for(i=0; i<x_max; i++) {
- mem[i] = 0.0;
- }
-
- prev_w = 0; prev_h = 0; prev_x = 0; prev_y = 0;
- index = 0;
- };
-
- ~Scalar() {
- delete mem;
- }
-
- void add_new_sample(float sample) {
- new_sample = sample;
- }
-
-};
-
-
-// update average of each spectrum point
-
-void new_data(float mag_dB[]) {
- int i;
-
- for(i=0; i<FDMDV_NSPEC; i++)
- av_mag[i] = (1.0 - BETA)*av_mag[i] + BETA*mag_dB[i];
-}
-
-
-/*------------------------------------------------------------------*\
-
- FUNCTION: per_frame_rx_processing()
- AUTHOR..: David Rowe
- DATE....: July 2012
-
- Called every rx frame to take a buffer of input modem samples and
- convert them to a buffer of output speech samples.
-
- The sample source could be a sound card or file. The sample source
- supplies a fixed number of samples with each call. However
- fdmdv_demod requires a variable number of samples for each call.
- This function will buffer as appropriate and call fdmdv_demod with
- the correct number of samples.
-
- The processing sequence is:
-
- collect demod input samples from sound card 1 A/D
- while we have enough samples:
- demod samples into bits
- decode bits into speech samples
- output a buffer of speech samples to sound card 2 D/A
-
- Note that sound card 1 and sound card 2 will have slightly different
- sample rates, as their sample clocks are not syncronised. We
- effectively lock the system to the demod A/D (sound card 1) sample
- rate. This ensures the demod gets a continuous sequence of samples,
- maintaining sync. Sample underflow or overflow will instead occur on
- the sound card 2 D/A. This is acceptable as a buffer of lost or
- extra speech samples is unlikely to be noticed.
-
- The situation is actually a little more complex than that. Through
- the demod timing estimation the buffers supplied to sound card D/A 2
- are effectively clocked at the remote modulator sound card D/A clock
- rate. We slip/gain buffers supplied to sound card 2 to compensate.
-
- The current demod handles varying clock rates by having a variable
- number of input samples, e.g. 120 160 (nominal) or 200. However the
- A/D always delivers a fixed number of samples.
-
- So we currently need some logic between the A/D and the demod:
- + A/D delivers fixed number of samples
- + demod processes a variable number of samples
- + this means we run demod 0,1 or 2 times, depending
- on number of buffered A/D samples
- + demod always outputs 1 frame of bits
- + so run demod and speech decoder 0, 1 or 2 times
-
- The ouput of the demod is codec voice data so it's OK if we miss or
- repeat a frame every now and again.
-
- TODOs:
-
- + this might work with arbitrary input and output buffer lengths,
- 0,1, or 2 only apply if we are inputting the nominal number of
- samples on every call.
-
- + so the I/O buffer sizes might not matter, as long as they of
- reasonable size (say twice the nominal size).
-
-\*------------------------------------------------------------------*/
-
-void per_frame_rx_processing(short output_buf[], /* output buf of decoded speech samples */
- int *n_output_buf, /* how many samples currently in output_buf[] */
- int codec_bits[], /* current frame of bits for decoder */
- short input_buf[], /* input buf of modem samples input to demod */
- int *n_input_buf, /* how many samples currently in input_buf[] */
- int *nin, /* amount of samples demod needs for next call */
- int *state, /* used to collect codec_bits[] halves */
- struct CODEC2 *c2 /* Codec 2 states */
- )
-{
- struct FDMDV_STATS stats;
- int sync_bit;
- float rx_fdm[FDMDV_MAX_SAMPLES_PER_FRAME];
- int rx_bits[FDMDV_BITS_PER_FRAME];
- uchar packed_bits[BYTES_PER_CODEC_FRAME];
- float rx_spec[FDMDV_NSPEC];
- int i, nin_prev, bit, byte;
- int next_state;
-
- assert(*n_input_buf <= (2*FDMDV_NOM_SAMPLES_PER_FRAME));
-
- /*
- This while loop will run the demod 0, 1 (nominal) or 2 times:
-
- 0: when tx sample clock runs faster than rx, occasionally we
- will run out of samples
-
- 1: normal, run decoder once, every 2nd frame output a frame of
- speech samples to D/A
-
- 2: when tx sample clock runs slower than rx, occasionally we will
- have enough samples to run demod twice.
-
- With a +/- 10 Hz sample clock difference at FS=8000Hz (+/- 1250
- ppm), case 0 or 1 occured about once every 30 seconds. This is
- no problem for the decoded audio.
- */
-
- while(*n_input_buf >= *nin) {
-
- // demod per frame processing
-
- for(i=0; i<*nin; i++)
- rx_fdm[i] = (float)input_buf[i]/FDMDV_SCALE;
- nin_prev = *nin;
- fdmdv_demod(fdmdv, rx_bits, &sync_bit, rx_fdm, nin);
- *n_input_buf -= nin_prev;
- assert(*n_input_buf >= 0);
-
- // shift input buffer
-
- for(i=0; i<*n_input_buf; i++)
- input_buf[i] = input_buf[i+nin_prev];
-
- // compute rx spectrum & get demod stats, and update GUI plot data
-
- fdmdv_get_rx_spectrum(fdmdv, rx_spec, rx_fdm, nin_prev);
- fdmdv_get_demod_stats(fdmdv, &stats);
- new_data(rx_spec);
- aScatter->add_new_samples(stats.rx_symbols);
- aTimingEst->add_new_sample(stats.rx_timing);
- aFreqEst->add_new_sample(stats.foff);
- aSNR->add_new_sample(stats.snr_est);
-
- /*
- State machine to:
-
- + Mute decoded audio when out of sync. The demod is synced
- when we are using the fine freq estimate and SNR is above
- a thresh.
-
- + Decode codec bits only if we have a 0,1 sync bit
- sequence. Collects two frames of demod bits to decode
- one frame of codec bits.
- */
-
- next_state = *state;
- switch (*state) {
- case 0:
- /* mute output audio when out of sync */
-
- if (*n_output_buf < 2*codec2_samples_per_frame(c2) - N8) {
- for(i=0; i<N8; i++)
- output_buf[*n_output_buf + i] = 0;
- *n_output_buf += N8;
- }
- assert(*n_output_buf <= (2*codec2_samples_per_frame(c2)));
-
- if ((stats.fest_coarse_fine == 1) && (stats.snr_est > 3.0))
- next_state = 1;
-
- break;
- case 1:
- if (sync_bit == 0) {
- next_state = 2;
-
- /* first half of frame of codec bits */
-
- memcpy(codec_bits, rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
- }
- else
- next_state = 1;
-
- if (stats.fest_coarse_fine == 0)
- next_state = 0;
-
- break;
- case 2:
- next_state = 1;
-
- if (stats.fest_coarse_fine == 0)
- next_state = 0;
-
- if (sync_bit == 1) {
- /* second half of frame of codec bits */
-
- memcpy(&codec_bits[FDMDV_BITS_PER_FRAME], rx_bits, FDMDV_BITS_PER_FRAME*sizeof(int));
-
- /* pack bits, MSB received first */
-
- bit = 7; byte = 0;
- memset(packed_bits, 0, BYTES_PER_CODEC_FRAME);
- for(i=0; i<BITS_PER_CODEC_FRAME; i++) {
- packed_bits[byte] |= (codec_bits[i] << bit);
- bit--;
- if (bit < 0) {
- bit = 7;
- byte++;
- }
- }
- assert(byte == BYTES_PER_CODEC_FRAME);
-
- /* add decoded speech to end of output buffer */
-
- if (*n_output_buf <= codec2_samples_per_frame(c2)) {
- codec2_decode(c2, &output_buf[*n_output_buf], packed_bits);
- *n_output_buf += codec2_samples_per_frame(c2);
- }
- assert(*n_output_buf <= (2*codec2_samples_per_frame(c2)));
-
- }
- break;
- }
- *state = next_state;
- }
-}
-
-
-/*
- Redraw windows every DT seconds.
-*/
-
-void update_gui(int nin, float *Ts) {
-
- *Ts += (float)nin/FS;
-
- *Ts += (float)nin/FS;
- if (*Ts >= DT) {
- *Ts -= DT;
- if (!zoomSpectrumWindow->shown() && !zoomWaterfallWindow->shown()) {
- aSpectrum->redraw();
- aWaterfall->redraw();
- aScatter->redraw();
- aTimingEst->redraw();
- aFreqEst->redraw();
- aSNR->redraw();
- }
- if (zoomSpectrumWindow->shown())
- aZoomedSpectrum->redraw();
- if (zoomWaterfallWindow->shown())
- aZoomedWaterfall->redraw();
- }
-}
-
-
-/*
- idle() is the FLTK function that gets continusouly called when FLTK
- is not doing GUI work. We use this function for providing file
- input to update the GUI when simulating real time operation.
-*/
-
-void idle(void*) {
- int ret, i;
-
- if (fin_name != NULL) {
- ret = fread(&input_buf[n_input_buf],
- sizeof(short),
- FDMDV_NOM_SAMPLES_PER_FRAME,
- fin);
- n_input_buf += FDMDV_NOM_SAMPLES_PER_FRAME;
-
- per_frame_rx_processing(output_buf, &n_output_buf,
- codec_bits,
- input_buf, &n_input_buf,
- &nin, &state, codec2);
-
- if (fout_name != NULL) {
- if (n_output_buf >= N8) {
- ret = fwrite(output_buf, sizeof(short), N8, fout);
- n_output_buf -= N8;
- assert(n_output_buf >= 0);
-
- /* shift speech sample output buffer */
-
- for(i=0; i<n_output_buf; i++)
- output_buf[i] = output_buf[i+N8];
- }
- }
- }
-
- update_gui(nin, &Ts);
-
- // simulate time delay from real world A/D input, and pause betwen
- // screen updates
-
- usleep(20000);
-}
-
-
-/*
- This routine will be called by the PortAudio engine when audio is
- available.
-*/
-
-static int callback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paCallBackData *cbData = (paCallBackData*)userData;
- uint i;
- short *rptr = (short*)inputBuffer;
- short *wptr = (short*)outputBuffer;
- float *in8k = cbData->in8k;
- float *in48k = cbData->in48k;
- float out8k[N8];
- float out48k[N48];
- short out48k_short[N48];
-
- (void) timeInfo;
- (void) statusFlags;
-
- assert(inputBuffer != NULL);
-
- /* Convert input model samples from 48 to 8 kHz ------------ */
-
- /* just use left channel */
-
- for(i=0; i<framesPerBuffer; i++,rptr+=2)
- in48k[i+FDMDV_OS_TAPS] = *rptr;
-
- /* downsample and update filter memory */
-
- fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
- for(i=0; i<FDMDV_OS_TAPS; i++)
- in48k[i] = in48k[i+framesPerBuffer];
-
- /* run demod, decoder and update GUI info ------------------ */
-
- for(i=0; i<N8; i++)
- input_buf[n_input_buf+i] = (short)out8k[i];
- n_input_buf += FDMDV_NOM_SAMPLES_PER_FRAME;
-
- per_frame_rx_processing(output_buf, &n_output_buf,
- codec_bits,
- input_buf, &n_input_buf,
- &nin, &state, codec2);
-
- /* if demod out of sync copy input audio from A/D to aid in tuning */
-
- if (n_output_buf >= N8) {
- if (state == 0) {
- for(i=0; i<N8; i++)
- in8k[MEM8+i] = out8k[i]; /* A/D signal */
- }
- else {
- for(i=0; i<N8; i++)
- in8k[MEM8+i] = output_buf[i]; /* decoded spech */
- }
- n_output_buf -= N8;
- }
- assert(n_output_buf >= 0);
-
- /* shift speech samples in output buffer */
-
- for(i=0; i<(uint)n_output_buf; i++)
- output_buf[i] = output_buf[i+N8];
-
- /* Convert output speech to 48 kHz sample rate ------------- */
-
- /* upsample and update filter memory */
-
- fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
- for(i=0; i<MEM8; i++)
- in8k[i] = in8k[i+N8];
-
- assert(outputBuffer != NULL);
-
- /* write signal to both channels */
-
- for(i=0; i<N48; i++)
- out48k_short[i] = (short)out48k[i];
- for(i=0; i<framesPerBuffer; i++,wptr+=2) {
- wptr[0] = out48k_short[i];
- wptr[1] = out48k_short[i];
- }
-
- return paContinue;
-}
-
-
-int arg_callback(int argc, char **argv, int &i) {
- if (argv[i][1] == 'i') {
- if ((i+1) >= argc)
- return 0;
- fin_name = argv[i+1];
- i += 2;
- return 2;
- }
- if (argv[i][1] == 'o') {
- if ((i+1) >= argc)
- return 0;
- fout_name = argv[i+1];
- i += 2;
- return 2;
- }
- if (argv[i][1] == 's') {
- if ((i+1) >= argc)
- return 0;
- sound_dev_name = argv[i+1];
- i += 2;
- return 2;
- }
- return 0;
-}
-
-/*------------------------------------------------------------*\
-
- MAIN
-
-\*------------------------------------------------------------*/
-
-int main(int argc, char **argv) {
- int ret;
- int i;
- PaStreamParameters inputParameters, outputParameters;
- paCallBackData cbData;
-
- i = 1;
- Fl::args(argc,argv,i,arg_callback);
-
- if (argc == 1) {
- printf("usage: %s [-i inputFdmdvRawFile] [-o outputRawSoundFile] [-s inputSoundDevice]\n", argv[0]);
- exit(0);
- }
-
- if (fin_name != NULL) {
- fin = fopen(fin_name,"rb");
- if (fin == NULL) {
- fprintf(stderr, "Error opening input fdmdv raw file %s\n", fin_name);
- exit(1);
- }
- }
-
- if (fout_name != NULL) {
- fout = fopen(fout_name,"wb");
- if (fout == NULL) {
- fprintf(stderr, "Error opening output speech raw file %s\n", fout_name);
- exit(1);
- }
- }
-
- for(i=0; i<FDMDV_NSPEC; i++)
- av_mag[i] = -40.0;
-
- fdmdv = fdmdv_create();
- codec2 = codec2_create(CODEC2_MODE_1400);
- output_buf = (short*)malloc(2*sizeof(short)*codec2_samples_per_frame(codec2));
-
- /*------------------------------------------------------------------------*\
-
- Init Sound Card I/O
-
- \*------------------------------------------------------------------------*/
-
- if (sound_dev_name != NULL) {
- for(i=0; i<MEM8; i++)
- cbData.in8k[i] = 0.0;
- for(i=0; i<FDMDV_OS_TAPS; i++)
- cbData.in48k[i] = 0.0;
-
- err = Pa_Initialize();
- if( err != paNoError ) goto pa_error;
- inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
- if (inputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default input device.\n");
- goto pa_error;
- }
- inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
- inputParameters.sampleFormat = paInt16;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
- inputParameters.hostApiSpecificStreamInfo = NULL;
-
- outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
- if (outputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default output device.\n");
- goto pa_error;
- }
- outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
- outputParameters.sampleFormat = paInt16;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- err = Pa_OpenStream(
- &stream,
- &inputParameters,
- &outputParameters,
- SAMPLE_RATE,
- N48,
- paClipOff,
- callback,
- &cbData);
-
- if( err != paNoError ) goto pa_error;
- }
-
- /*------------------------------------------------------------------------*\
-
- Init GUI
-
- \*------------------------------------------------------------------------*/
-
- // recommended to prevent dithering and stopped display being
- // covered by black flickering squares
-
- Fl::visual(FL_RGB);
-
- // set up main window
-
- window = new Fl_Window(W, SP+H2+SP+SP+H2+SP, "fl_fmdv");
- //window->size_range(100, 100);
- //window->resizable();
- aSpectrum = new Spectrum(SP, SP, W3-2*SP, H2);
- aWaterfall = new Waterfall(SP, SP+H2+SP+SP, W3-2*SP, H2);
- aScatter = new Scatter(W3+SP, SP, W3-2*SP, H2);
- aTimingEst = new Scalar(W3+SP, SP+H2+SP+SP, W3-2*SP, H2, 100, 80, "Timing Est");
- aFreqEst = new Scalar(2*W3+SP, SP, W3-2*SP, H2, 100, 100, "Frequency Est");
- aSNR = new Scalar(2*W3+SP, SP+H2+SP+SP, W3-2*SP, H2, 100, 20, "SNR");
-
- Fl::add_idle(idle);
-
- window->end();
-
- // set up zoomed spectrum window
-
- zoomSpectrumWindow = new Fl_Window(W, H, "Spectrum");
- aZoomedSpectrum = new Spectrum(SP, SP, W-2*SP, H-2*SP);
- zoomSpectrumWindow->end();
-
- // set up zoomed waterfall window
-
- zoomWaterfallWindow = new Fl_Window(W, H, "Waterfall");
- aZoomedWaterfall = new Waterfall(SP, SP, W-2*SP, H-2*SP);
- zoomWaterfallWindow->end();
-
- if (sound_dev_name != NULL) {
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto pa_error;
- }
-
- // show the main window and start running
-
- window->show(argc, argv);
- Fl::run();
-
- if (sound_dev_name != NULL) {
- err = Pa_StopStream( stream );
- if( err != paNoError ) goto pa_error;
- Pa_CloseStream( stream );
- Pa_Terminate();
- }
-
- fdmdv_destroy(fdmdv);
- codec2_destroy(codec2);
- free(output_buf);
-
- if (fin_name != NULL)
- fclose(fin);
- if (fout_name != NULL)
- fclose(fout);
-
- return ret;
-
- // Portaudio error handling
-
-pa_error:
- if( stream ) {
- Pa_AbortStream( stream );
- Pa_CloseStream( stream );
- }
- Pa_Terminate();
- fprintf( stderr, "An error occured while using the portaudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- return -1;
-}
+++ /dev/null
-# Makefile for Portaudio test programs
-# Requires Portaudio V19
-
-CFLAGS = -g -Wall -I../src
-LIBS = -lm -lportaudio -pthread
-SRC = ../src/fdmdv.c ../src/kiss_fft.c ../src/fifo.c
-
-all: pa_rec pa_play pa_recplay pa_impresp
-
-pa_rec: Makefile pa_rec.c $(SRC)
- gcc $(CFLAGS) pa_rec.c $(SRC) -o pa_rec $(LIBS)
-
-pa_play: Makefile pa_play.c $(SRC)
- gcc $(CFLAGS) pa_play.c $(SRC) -o pa_play $(LIBS)
-
-pa_recplay: Makefile pa_recplay.c $(SRC)
- gcc $(CFLAGS) pa_recplay.c $(SRC) -o pa_recplay $(LIBS)
-
-pa_impresp: Makefile pa_impresp.c $(SRC)
- gcc $(CFLAGS) pa_impresp.c $(SRC) -o pa_impresp $(LIBS)
-
-clean:
- rm -f pa_rec pa_play pa_recplay
+++ /dev/null
-/*
- pa_impresp.c
- David Rowe
- August 29 2012
-
- Measures the impulse reponse of the path between the speaker and
- microphone. Used to explore why Codec audio quality is
- different through a speaker and headphones.
-
- Modified from pa_playrec.c
-*/
-
-/*
- * $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "portaudio.h"
-#include "fdmdv.h"
-
-#define SAMPLE_RATE 48000 /* 48 kHz sampling rate rec. as we
- can trust accuracy of sound
- card */
-#define N8 160 /* processing buffer size at 8 kHz */
-#define N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
-#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
-#define NUM_CHANNELS 2 /* I think most sound cards prefer
- stereo, we will convert to mono
- as we sample */
-
-#define IMPULSE_AMP 16384 /* amplitide of impulse */
-#define IMPULSE_PERIOD 0.1 /* period (dly between impulses) in secs */
-
-/* state information passed to call back */
-
-typedef struct {
- float in48k[FDMDV_OS_TAPS + N48];
- float in8k[MEM8 + N8];
- FILE *fimp;
- float *impulse_buf;
- int impulse_buf_length;
- int impulse_sample_count;
- int framesLeft;
-} paTestData;
-
-
-/*
- This routine will be called by the PortAudio engine when audio is
- required. It may be called at interrupt level on some machines so
- don't do anything that could mess up the system like calling
- malloc() or free().
-*/
-
-static int callback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paTestData *data = (paTestData*)userData;
- int i;
- short *rptr = (short*)inputBuffer;
- short *wptr = (short*)outputBuffer;
- float *in8k = data->in8k;
- float *in48k = data->in48k;
- float out8k[N8];
- float out48k[N48];
- short out48k_short[N48];
- short out8k_short[N8];
-
- (void) timeInfo;
- (void) statusFlags;
-
- assert(inputBuffer != NULL);
-
- /* just use left channel */
-
- for(i=0; i<framesPerBuffer; i++,rptr+=2)
- data->in48k[i+FDMDV_OS_TAPS] = *rptr;
-
- /* downsample and update filter memory */
-
- fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
- for(i=0; i<FDMDV_OS_TAPS; i++)
- in48k[i] = in48k[i+framesPerBuffer];
-
- /* write impulse response to disk */
-
- for(i=0; i<N8; i++)
- out8k_short[i] = out8k[i];
- fwrite(out8k_short, sizeof(short), N8, data->fimp);
-
- /* play side, read from impulse buffer */
-
- for(i=0; i<N8; i++) {
- in8k[MEM8+i] = data->impulse_buf[data->impulse_sample_count];
- data->impulse_sample_count++;
- if (data->impulse_sample_count == data->impulse_buf_length)
- data->impulse_sample_count = 0;
- }
-
- /* upsample and update filter memory */
-
- fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
- for(i=0; i<MEM8; i++)
- in8k[i] = in8k[i+N8];
-
- assert(outputBuffer != NULL);
-
- /* write signal to both channels */
-
- for(i=0; i<N48; i++)
- out48k_short[i] = (short)out48k[i];
- for(i=0; i<framesPerBuffer; i++,wptr+=2) {
- wptr[0] = out48k_short[i];
- wptr[1] = out48k_short[i];
- }
-
- data->framesLeft -= framesPerBuffer;
- if (data->framesLeft > 0)
- return paContinue;
- else
- return paComplete;
-}
-
-int main(int argc, char *argv[])
-{
- PaStreamParameters inputParameters, outputParameters;
- PaStream* stream;
- PaError err = paNoError;
- paTestData data;
- int i, numSecs;
-
- if (argc != 3) {
- printf("usage: %s impulseRawFile time(s)\n", argv[0]);
- exit(0);
- }
-
- data.fimp = fopen(argv[1], "wb");
- if (data.fimp == NULL) {
- printf("Error opening impulse output file %s\n", argv[1]);
- exit(1);
- }
-
- numSecs = atoi(argv[2]);
- data.framesLeft = numSecs * SAMPLE_RATE;
-
- /* init filter states */
-
- for(i=0; i<MEM8; i++)
- data.in8k[i] = 0.0;
- for(i=0; i<FDMDV_OS_TAPS; i++)
- data.in48k[i] = 0.0;
-
- /* init imupulse */
-
- data.impulse_buf_length = IMPULSE_PERIOD*(SAMPLE_RATE/FDMDV_OS);
- printf("%d\n",data.impulse_buf_length);
- data.impulse_buf = (float*)malloc(data.impulse_buf_length*sizeof(float));
- assert(data.impulse_buf != NULL);
- data.impulse_buf[0] = IMPULSE_AMP;
- for(i=1; i<data.impulse_buf_length; i++)
- data.impulse_buf[i] = 0;
- data.impulse_sample_count = 0;
-
- err = Pa_Initialize();
- if( err != paNoError ) goto done;
-
- inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
- if (inputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default input device.\n");
- goto done;
- }
- inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
- inputParameters.sampleFormat = paInt16;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
- inputParameters.hostApiSpecificStreamInfo = NULL;
-
- outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
- if (outputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default output device.\n");
- goto done;
- }
- outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
- outputParameters.sampleFormat = paInt16;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- /* Play some audio --------------------------------------------- */
-
- err = Pa_OpenStream(
- &stream,
- &inputParameters,
- &outputParameters,
- SAMPLE_RATE,
- N48,
- paClipOff,
- callback,
- &data );
- if( err != paNoError ) goto done;
-
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto done;
-
- while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
- {
- Pa_Sleep(100);
- }
- if( err < 0 ) goto done;
-
- err = Pa_CloseStream( stream );
- if( err != paNoError ) goto done;
-
-
-done:
- Pa_Terminate();
- if( err != paNoError )
- {
- fprintf( stderr, "An error occured while using the portaudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- err = 1; /* Always return 0 or 1, but no other return codes. */
- }
-
- fclose(data.fimp);
-
- return err;
-}
-
+++ /dev/null
-/*
- pa_play.c
- David Rowe
- July 8 2012
-
- Converts samples from a 16 bit short 8000 Hz rawfile to 480000Hz
- sample rate and plays them using the default sound device. Used as
- an intermediate step in Portaudio integration.
-
- Modified from paex_record.c Portaudio example. Original author
- author Phil Burk http://www.softsynth.com
-*/
-
-/*
- * $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "portaudio.h"
-#include "fdmdv.h"
-
-#define SAMPLE_RATE 48000 /* 48 kHz sampling rate rec. as we
- can trust accuracy of sound
- card */
-#define N8 160 /* processing buffer size at 8 kHz */
-#define N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
-#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
-#define NUM_CHANNELS 2 /* I think most sound cards prefer
- stereo, we will convert to mono
- as we sample */
-
-/* state information passed to call back */
-
-typedef struct {
- FILE *fin;
- float in8k[MEM8 + N8];
-} paTestData;
-
-
-/*
- This routine will be called by the PortAudio engine when audio is
- required. It may be called at interrupt level on some machines so
- don't do anything that could mess up the system like calling
- malloc() or free().
-*/
-
-static int playCallback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paTestData *data = (paTestData*)userData;
- FILE *fin = data->fin;
- int i, nread;
- int finished;
- short *wptr = (short*)outputBuffer;
- float *in8k = data->in8k;
- float out48k[N48];
- short out48k_short[N48];
- short in8k_short[N8];
-
- (void) outputBuffer; /* Prevent unused variable warnings. */
- (void) timeInfo;
- (void) statusFlags;
- (void) userData;
-
- /* note Portaudio docs recs. against making systems calls like
- fwrite() in this callback but seems to work OK */
-
- nread = fread(in8k_short, sizeof(short), N8, fin);
- if (nread == N8)
- finished = paContinue;
- else
- finished = paComplete;
-
- for(i=0; i<N8; i++)
- in8k[MEM8+i] = in8k_short[i];
-
- /* upsample and update filter memory */
-
- fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
- for(i=0; i<MEM8; i++)
- in8k[i] = in8k[i+N8];
-
- assert(outputBuffer != NULL);
-
- /* write signal to both channels */
-
- for(i=0; i<N48; i++)
- out48k_short[i] = (short)out48k[i];
- for(i=0; i<framesPerBuffer; i++,wptr+=2) {
- wptr[0] = out48k_short[i];
- wptr[1] = out48k_short[i];
- }
-
- return finished;
-}
-
-int main(int argc, char *argv[])
-{
- PaStreamParameters outputParameters;
- PaStream* stream;
- PaError err = paNoError;
- paTestData data;
- int i;
-
- if (argc != 2) {
- printf("usage: %s rawFile\n", argv[0]);
- exit(0);
- }
-
- data.fin = fopen(argv[1], "rt");
- if (data.fin == NULL) {
- printf("Error opening input raw file %s\n", argv[1]);
- exit(1);
- }
-
- for(i=0; i<MEM8; i++)
- data.in8k[i] = 0.0;
-
- err = Pa_Initialize();
- if( err != paNoError ) goto done;
-
- outputParameters.device = Pa_GetDefaultOutputDevice(); /* default input device */
- if (outputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default output device.\n");
- goto done;
- }
- outputParameters.channelCount = NUM_CHANNELS; /* stereo input */
- outputParameters.sampleFormat = paInt16;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- /* Play some audio --------------------------------------------- */
-
- err = Pa_OpenStream(
- &stream,
- NULL,
- &outputParameters,
- SAMPLE_RATE,
- N48,
- paClipOff,
- playCallback,
- &data );
- if( err != paNoError ) goto done;
-
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto done;
-
- while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
- {
- Pa_Sleep(100);
- }
- if( err < 0 ) goto done;
-
- err = Pa_CloseStream( stream );
- if( err != paNoError ) goto done;
-
- fclose(data.fin);
-
-
-done:
- Pa_Terminate();
- if( err != paNoError )
- {
- fprintf( stderr, "An error occured while using the portaudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- err = 1; /* Always return 0 or 1, but no other return codes. */
- }
- return err;
-}
-
+++ /dev/null
-/*
- pa_rec.c
- David Rowe
- July 6 2012
-
- Records at 48000 Hz from default sound device, convertes to 8 kHz,
- and saves to raw file. Used to get experience with Portaudio.
-
- Modified from paex_record.c Portaudio example. Original author
- author Phil Burk http://www.softsynth.com
-
- To Build:
-
- gcc paex_rec.c -o paex_rec -lm -lrt -lportaudio -pthread
-*/
-
-/*
- * $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "portaudio.h"
-#include "fdmdv.h"
-
-#define SAMPLE_RATE 48000 /* 48 kHz sampling rate rec. as we
- can trust accuracy of sound
- card */
-#define N8 160 /* processing buffer size at 8 kHz */
-#define N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
-#define NUM_CHANNELS 2 /* I think most sound cards prefer
- stereo, we will convert to mono
- as we sample */
-
-/* state information passed to call back */
-
-typedef struct {
- FILE *fout;
- int framesLeft;
- float in48k[FDMDV_OS_TAPS + N48];
-} paTestData;
-
-
-/*
- This routine will be called by the PortAudio engine when audio is
- available. It may be called at interrupt level on some machines so
- don't do anything that could mess up the system like calling
- malloc() or free().
-*/
-
-static int recordCallback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paTestData *data = (paTestData*)userData;
- FILE *fout = data->fout;
- int framesToCopy;
- int i;
- int finished;
- short *rptr = (short*)inputBuffer;
- float out8k[N8];
- short out8k_short[N8];
-
- (void) outputBuffer; /* Prevent unused variable warnings. */
- (void) timeInfo;
- (void) statusFlags;
- (void) userData;
-
- if (data->framesLeft < framesPerBuffer) {
- framesToCopy = data->framesLeft;
- finished = paComplete;
- }
- else {
- framesToCopy = framesPerBuffer;
- finished = paContinue;
- }
- data->framesLeft -= framesToCopy;
-
- assert(inputBuffer != NULL);
-
- /* just use left channel */
-
- for(i=0; i<framesToCopy; i++,rptr+=2)
- data->in48k[i+FDMDV_OS_TAPS] = *rptr;
-
- /* downsample and update filter memory */
-
- fdmdv_48_to_8(out8k, &data->in48k[FDMDV_OS_TAPS], N8);
- for(i=0; i<FDMDV_OS_TAPS; i++)
- data->in48k[i] = data->in48k[i+framesToCopy];
-
- /* save 8k to disk */
-
- for(i=0; i<N8; i++)
- out8k_short[i] = (short)out8k[i];
-
- /* note Portaudio docs recs. against making systems calls like
- fwrite() in this callback but seems to work OK */
-
- fwrite(out8k_short, sizeof(short), N8, fout);
-
- return finished;
-}
-
-int main(int argc, char *argv[])
-{
- PaStreamParameters inputParameters;
- PaStream* stream;
- PaError err = paNoError;
- paTestData data;
- int i;
- int numSecs;
-
- if (argc != 3) {
- printf("usage: %s rawFile time(s)\n", argv[0]);
- exit(0);
- }
-
- data.fout = fopen(argv[1], "wt");
- if (data.fout == NULL) {
- printf("Error opening output raw file %s\n", argv[1]);
- exit(1);
- }
-
- numSecs = atoi(argv[2]);
- data.framesLeft = numSecs * SAMPLE_RATE;
-
- for(i=0; i<FDMDV_OS_TAPS; i++)
- data.in48k[i] = 0.0;
-
- err = Pa_Initialize();
- if( err != paNoError ) goto done;
-
- printf( "PortAudio version number = %d\nPortAudio version text = '%s'\n",
- Pa_GetVersion(), Pa_GetVersionText() );
-
- inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
- if (inputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default input device.\n");
- goto done;
- }
- inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
- inputParameters.sampleFormat = paInt16;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
- inputParameters.hostApiSpecificStreamInfo = NULL;
-
- /* Record some audio --------------------------------------------- */
-
- err = Pa_OpenStream(
- &stream,
- &inputParameters,
- NULL, /* &outputParameters, */
- SAMPLE_RATE,
- N48,
- paClipOff, /* we won't output out of range samples so don't bother clipping them */
- recordCallback,
- &data );
- if( err != paNoError ) goto done;
-
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto done;
-
- while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
- {
- Pa_Sleep(100);
- }
- if( err < 0 ) goto done;
-
- err = Pa_CloseStream( stream );
- if( err != paNoError ) goto done;
-
- fclose(data.fout);
-
-
-done:
- Pa_Terminate();
- if( err != paNoError )
- {
- fprintf( stderr, "An error occured while using the portaudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- err = 1; /* Always return 0 or 1, but no other return codes. */
- }
- return err;
-}
-
+++ /dev/null
-/*
- pa_recplay.c
- David Rowe
- July 8 2012
-
- Echos audio from sound card input to sound card output. Samples at
- 48 kHz, converts to 8 kHz, converts back to 48kHz, and plays using
- the default sound device. Used as an intermediate step in
- Portaudio integration.
-
- Modified from paex_record.c Portaudio example. Original author
- author Phil Burk http://www.softsynth.com
-*/
-
-/*
- * $Id: paex_record.c 1752 2011-09-08 03:21:55Z philburk $
- *
- * This program uses the PortAudio Portable Audio Library.
- * For more information see: http://www.portaudio.com
- * Copyright (c) 1999-2000 Ross Bencina and Phil Burk
- *
- * Permission is hereby granted, free of charge, to any person obtaining
- * a copy of this software and associated documentation files
- * (the "Software"), to deal in the Software without restriction,
- * including without limitation the rights to use, copy, modify, merge,
- * publish, distribute, sublicense, and/or sell copies of the Software,
- * and to permit persons to whom the Software is furnished to do so,
- * subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be
- * included in all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include "portaudio.h"
-#include "fdmdv.h"
-#include "fifo.h"
-
-#define SAMPLE_RATE 48000 /* 48 kHz sampling rate rec. as we
- can trust accuracy of sound
- card */
-#define N8 160 /* processing buffer size at 8 kHz */
-#define N48 (N8*FDMDV_OS) /* processing buffer size at 48 kHz */
-#define MEM8 (FDMDV_OS_TAPS/FDMDV_OS)
-#define NUM_CHANNELS 2 /* I think most sound cards prefer
- stereo, we will convert to mono
- as we sample */
-#define MAX_FPB 2048 /* maximum value of framesPerBuffer */
-
-/* state information passed to call back */
-
-typedef struct {
- float in48k[FDMDV_OS_TAPS + N48];
- float in8k[MEM8 + N8];
- struct FIFO *infifo;
- struct FIFO *outfifo;
-} paTestData;
-
-
-/*
- This routine will be called by the PortAudio engine when audio is
- required. It may be called at interrupt level on some machines so
- don't do anything that could mess up the system like calling
- malloc() or free().
-*/
-
-static int callback( const void *inputBuffer, void *outputBuffer,
- unsigned long framesPerBuffer,
- const PaStreamCallbackTimeInfo* timeInfo,
- PaStreamCallbackFlags statusFlags,
- void *userData )
-{
- paTestData *data = (paTestData*)userData;
- int i;
- short *rptr = (short*)inputBuffer;
- short *wptr = (short*)outputBuffer;
- float *in8k = data->in8k;
- float *in48k = data->in48k;
- float out8k[N8];
- float out48k[N48];
- short out48k_short[N48];
- short in48k_short[N48];
- short indata[MAX_FPB];
- short outdata[MAX_FPB];
-
- (void) timeInfo;
- (void) statusFlags;
-
- assert(inputBuffer != NULL);
- assert(outputBuffer != NULL);
-
- /*
- framesPerBuffer is portaudio-speak for number of samples we
- actually get from the record side and need to provide to the
- play side. On Linux (at least) it was found that
- framesPerBuffer may not always be what we ask for in the
- framesPerBuffer field of Pa_OpenStream. For example a request
- for 960 sample buffers lead to framesPerBuffer = 1024.
-
- To perform the 48 to 8 kHz conversion we need an integer
- multiple of FDMDV_OS samples to support the interpolation and
- decimation. As we can't guarantee the size of framesPerBuffer
- we do a little FIFO buffering.
- */
-
- //printf("framesPerBuffer: %d N48 %d\n", framesPerBuffer, N48);
-
- /* assemble a mono buffer (just use left channel) and write to FIFO */
-
- assert(framesPerBuffer < MAX_FPB);
- for(i=0; i<framesPerBuffer; i++,rptr+=2)
- indata[i] = *rptr;
- fifo_write(data->infifo, indata, framesPerBuffer);
-
- /* while we have enough samples available ... */
-
- //printf("infifo before: %d\n", fifo_n(data->infifo));
- while (fifo_read(data->infifo, in48k_short, N48) == 0) {
-
- /* convert to float */
-
- for(i=0; i<N48; i++)
- in48k[FDMDV_OS_TAPS + i] = in48k_short[i];
-
- /* downsample and update filter memory */
-
- fdmdv_48_to_8(out8k, &in48k[FDMDV_OS_TAPS], N8);
- for(i=0; i<FDMDV_OS_TAPS; i++)
- in48k[i] = in48k[i+N48];
-
- /* play side, back up to 8k */
-
- for(i=0; i<N8; i++)
- in8k[MEM8+i] = out8k[i];
-
- /* upsample and update filter memory */
-
- fdmdv_8_to_48(out48k, &in8k[MEM8], N8);
- for(i=0; i<MEM8; i++)
- in8k[i] = in8k[i+N8];
-
- /* write signal to both channels */
-
- for(i=0; i<N48; i++)
- out48k_short[i] = (short)out48k[i];
-
- fifo_write(data->outfifo, out48k_short, N48);
- }
- //printf("infifo after: %d\n", fifo_n(data->infifo));
- //printf("outfifo : %d\n", fifo_n(data->outfifo));
-
-
- /* OK now set up output samples */
-
- if (fifo_read(data->outfifo, outdata, framesPerBuffer) == 0) {
-
- /* write signal to both channels */
-
- for(i=0; i<framesPerBuffer; i++,wptr+=2) {
- wptr[0] = outdata[i];
- wptr[1] = outdata[i];
- }
- }
- else {
- //printf("no data\n");
- /* zero output if no data available */
- for(i=0; i<framesPerBuffer; i++,wptr+=2) {
- wptr[0] = 0;
- wptr[1] = 0;
- }
- }
-
- return paContinue;
-}
-
-int main(int argc, char *argv[])
-{
- PaStreamParameters inputParameters, outputParameters;
- PaStream* stream;
- PaError err = paNoError;
- paTestData data;
- int i;
-
- /* init callback data */
-
- for(i=0; i<MEM8; i++)
- data.in8k[i] = 0.0;
- for(i=0; i<FDMDV_OS_TAPS; i++)
- data.in48k[i] = 0.0;
-
- data.infifo = fifo_create(2*N48);
- data.outfifo = fifo_create(2*N48);
-
- /* init port audio */
-
- err = Pa_Initialize();
- if( err != paNoError ) goto done;
-
- inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
- if (inputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default input device.\n");
- goto done;
- }
- inputParameters.channelCount = NUM_CHANNELS; /* stereo input */
- inputParameters.sampleFormat = paInt16;
- inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
- inputParameters.hostApiSpecificStreamInfo = NULL;
-
- outputParameters.device = Pa_GetDefaultOutputDevice(); /* default output device */
- if (outputParameters.device == paNoDevice) {
- fprintf(stderr,"Error: No default output device.\n");
- goto done;
- }
- outputParameters.channelCount = NUM_CHANNELS; /* stereo output */
- outputParameters.sampleFormat = paInt16;
- outputParameters.suggestedLatency = Pa_GetDeviceInfo( outputParameters.device )->defaultLowOutputLatency;
- outputParameters.hostApiSpecificStreamInfo = NULL;
-
- /* Play some audio --------------------------------------------- */
-
- err = Pa_OpenStream(
- &stream,
- &inputParameters,
- &outputParameters,
- SAMPLE_RATE,
- 512,
- paClipOff,
- callback,
- &data );
- if( err != paNoError ) goto done;
-
- err = Pa_StartStream( stream );
- if( err != paNoError ) goto done;
-
- while( ( err = Pa_IsStreamActive( stream ) ) == 1 )
- {
- Pa_Sleep(100);
- }
- if( err < 0 ) goto done;
-
- err = Pa_CloseStream( stream );
- if( err != paNoError ) goto done;
-
-
-done:
- Pa_Terminate();
- if( err != paNoError )
- {
- fprintf( stderr, "An error occured while using the portaudio stream\n" );
- fprintf( stderr, "Error number: %d\n", err );
- fprintf( stderr, "Error message: %s\n", Pa_GetErrorText( err ) );
- err = 1; /* Always return 0 or 1, but no other return codes. */
- }
-
- fifo_destroy(data.infifo);
- fifo_destroy(data.outfifo);
-
- return err;
-}
-
+++ /dev/null
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
+++ /dev/null
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
+++ /dev/null
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
+++ /dev/null
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-1
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
-0
+++ /dev/null
-# Win32 Makefile derived from the fine work of Peter Lawrence:\r
-# http://code.google.com/p/codec2demo/\r
-#\r
-# David Rowe June 2012\r
-#\r
-# This makefile assumes the Linux version has been compiled first to generate\r
-# the machine-generated codebook source files. It is designed to be cross compiled on\r
-# Linux. \r
-# \r
-\r
-# uncomment under Windows\r
-#CC_PREFIX = \r
-# uncomment under Linux (to cross-compile for Windows)\r
-CC_PREFIX = i586-mingw32msvc-\r
-\r
-DLLNAME = codec2.dll\r
-LIBNAME = codec2.lib\r
-\r
-CFLAGS = -O2 -Wall -D__CODEC2_WIN32__\r
-\r
-HDRS = ../src/codec2.h ../src/codec2_fdmdv.h\r
-\r
-OBJS = dump.o lpc.o nlp.o postfilter.o sine.o codec2.o fdmdv.o kiss_fft.o interp.o lsp.o phase.o quantise.o pack.o codebook.o codebookd.o codebookvq.o codebookjnd.o codebookjvm.o codebookdt.o codebookge.o\r
-\r
-all: $(DLLNAME) c2demo.exe c2enc.exe c2dec.exe fdmdv_get_test_bits.exe fdmdv_mod.exe fdmdv_demod.exe fdmdv_put_test_bits.exe\r
-\r
-$(DLLNAME): $(OBJS)\r
- $(CC_PREFIX)gcc -shared -o $(DLLNAME) $(OBJS) -Wl,--out-implib,$(LIBNAME)\r
-\r
-%.o: ../src/%.c $(HDRS) Makefile\r
- $(CC_PREFIX)gcc $(CFLAGS) -D__CODEC2_BUILDING_DLL__ -c $< -o $@\r
-\r
-c2demo.exe: ../src/c2demo.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-c2enc.exe: ../src/c2enc.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-c2dec.exe: ../src/c2dec.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-fdmdv_get_test_bits.exe: ../src/fdmdv_get_test_bits.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-fdmdv_mod.exe: ../src/fdmdv_mod.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-fdmdv_demod.exe: ../src/fdmdv_demod.c ../src/octave.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< ../src/octave.c -o $@ $(LIBNAME)\r
-\r
-fdmdv_put_test_bits.exe: ../src/fdmdv_put_test_bits.c $(DLLNAME) $(LIBNAME)\r
- $(CC_PREFIX)gcc $(CFLAGS) $< -o $@ $(LIBNAME)\r
-\r
-clean:\r
- rm -f $(DLLNAME) $(LIBNAME)\r
- rm -f *.o *.exe\r
-\r