mirror of
https://github.com/ggerganov/ggwave.git
synced 2026-02-07 17:54:39 +08:00
ggwave v0.2.0 (#20)
* ggwave : add support for fixed length transmissions * spectrogram : add sample rate offset for debugging purposes * gwave : fix decoding bug * waver : wip * wip * remove post-marker frames * add resampler * ggwave : input/output resampling * ggwave : fix python build * ggwave : update spm * ggwave : refactor duplicate encode/decode code * ggwave : fix sound marker detection * waver : fix typo * ggwave : fix uninitialized members * ggwave : more sensitive receive
This commit is contained in:
@@ -4,6 +4,7 @@ set(TARGET ggwave)
|
||||
|
||||
add_library(${TARGET}
|
||||
ggwave.cpp
|
||||
resampler.cpp
|
||||
)
|
||||
|
||||
target_include_directories(${TARGET} PUBLIC
|
||||
|
||||
848
src/ggwave.cpp
848
src/ggwave.cpp
File diff suppressed because it is too large
Load Diff
110
src/resampler.cpp
Normal file
110
src/resampler.cpp
Normal file
@@ -0,0 +1,110 @@
|
||||
#include "resampler.h"
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdio>
|
||||
|
||||
namespace {
|
||||
double linear_interp(double first_number, double second_number, double fraction) {
|
||||
return (first_number + ((second_number - first_number)*fraction));
|
||||
}
|
||||
}
|
||||
|
||||
int Resampler::resample(
|
||||
float factor,
|
||||
int nSamples,
|
||||
const float * samplesInp,
|
||||
float * samplesOut) {
|
||||
if (factor != m_lastFactor) {
|
||||
make_sinc();
|
||||
m_lastFactor = factor;
|
||||
}
|
||||
|
||||
int idxInp = 0;
|
||||
int idxOut = 0;
|
||||
int notDone = 1;
|
||||
double time_now = 0.0;
|
||||
long num_samples = nSamples;
|
||||
long int_time = 0;
|
||||
long last_time = 0;
|
||||
float data_in = samplesInp[idxInp];
|
||||
float data_out;
|
||||
double one_over_factor = 1.0;
|
||||
while (notDone) {
|
||||
double temp1 = 0.0;
|
||||
long left_limit = time_now - kWidth + 1; /* leftmost neighboring sample used for interp.*/
|
||||
long right_limit = time_now + kWidth; /* rightmost leftmost neighboring sample used for interp.*/
|
||||
if (left_limit<0) left_limit = 0;
|
||||
if (right_limit>num_samples) right_limit = num_samples;
|
||||
if (factor<1.0) {
|
||||
for (int j=left_limit;j<right_limit;j++) {
|
||||
temp1 += gimme_data(j-int_time)*sinc(time_now - (double) j);
|
||||
}
|
||||
data_out = temp1;
|
||||
}
|
||||
else {
|
||||
one_over_factor = 1.0 / factor;
|
||||
for (int j=left_limit;j<right_limit;j++) {
|
||||
temp1 += gimme_data(j-int_time)*one_over_factor*sinc(one_over_factor * (time_now - (double) j));
|
||||
}
|
||||
data_out = temp1;
|
||||
}
|
||||
|
||||
//printf("%8.8f %8.8f\n", data_in, data_out);
|
||||
samplesOut[idxOut++] = data_out;
|
||||
time_now += factor;
|
||||
last_time = int_time;
|
||||
int_time = time_now;
|
||||
while(last_time<int_time) {
|
||||
if (++idxInp == nSamples) {
|
||||
notDone = 0;
|
||||
} else {
|
||||
data_in = samplesInp[idxInp];
|
||||
}
|
||||
new_data(data_in);
|
||||
last_time += 1;
|
||||
}
|
||||
// if (!(int_time % 1000)) printf("Sample # %li\n",int_time);
|
||||
//if (!(int_time % 1000)) {
|
||||
// printf(".");
|
||||
// fflush(stdout);
|
||||
//}
|
||||
}
|
||||
|
||||
return idxOut;
|
||||
}
|
||||
|
||||
float Resampler::gimme_data(long j) const {
|
||||
return m_delayBuffer[(int) j + kWidth];
|
||||
}
|
||||
|
||||
void Resampler::new_data(float data) {
|
||||
for (int i = 0; i < kDelaySize - 5; i++) {
|
||||
m_delayBuffer[i] = m_delayBuffer[i + 1];
|
||||
}
|
||||
m_delayBuffer[kDelaySize - 5] = data;
|
||||
}
|
||||
|
||||
void Resampler::make_sinc() {
|
||||
double temp, win_freq, win;
|
||||
win_freq = M_PI/kWidth/kSamplesPerZeroCrossing;
|
||||
m_sincTable[0] = 1.0;
|
||||
for (int i = 1; i < kWidth*kSamplesPerZeroCrossing;i++) {
|
||||
temp = (double) i*M_PI/kSamplesPerZeroCrossing;
|
||||
m_sincTable[i] = sin(temp)/temp;
|
||||
win = 0.5 + 0.5*cos(win_freq*i);
|
||||
m_sincTable[i] *= win;
|
||||
}
|
||||
}
|
||||
|
||||
double Resampler::sinc(double x) const {
|
||||
int low;
|
||||
double temp, delta;
|
||||
if (fabs(x) >= kWidth - 1) {
|
||||
return 0.0;
|
||||
} else {
|
||||
temp = fabs(x) * (double) kSamplesPerZeroCrossing;
|
||||
low = temp; /* these are interpolation steps */
|
||||
delta = temp - low; /* and can be ommited if desired */
|
||||
return linear_interp(m_sincTable[low], m_sincTable[low + 1], delta);
|
||||
}
|
||||
}
|
||||
32
src/resampler.h
Normal file
32
src/resampler.h
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
class Resampler {
|
||||
public:
|
||||
int resample(
|
||||
float factor,
|
||||
int nSamples,
|
||||
const float * samplesInp,
|
||||
float * samplesOut);
|
||||
private:
|
||||
float gimme_data(long j) const;
|
||||
void new_data(float data);
|
||||
void make_sinc();
|
||||
double sinc(double x) const;
|
||||
|
||||
/* this controls the number of neighboring samples
|
||||
which are used to interpolate the new samples. The
|
||||
processing time is linearly related to this width */
|
||||
static const int kWidth = 64;
|
||||
|
||||
static const int kDelaySize = 140;
|
||||
|
||||
/* this defines how finely the sinc function
|
||||
is sampled for storage in the table */
|
||||
static const int kSamplesPerZeroCrossing = 32;
|
||||
|
||||
float m_sincTable[kWidth*kSamplesPerZeroCrossing] = { 0.0 };
|
||||
|
||||
float m_delayBuffer[3*kWidth] = { 0 };
|
||||
|
||||
float m_lastFactor = -1.0f;
|
||||
};
|
||||
Reference in New Issue
Block a user