the most basic, generally not-correct linear interpolating resampling filter

pull/18/head
Dimitri Diakopoulos 10 years ago
parent 892c798f9f
commit ce56c943b9

@ -40,8 +40,8 @@ int main(int argc, const char **argv) try
// 1-channel wave
//loader.Load(fileData.get(), "test_data/1ch/44100/8/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/16/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/24/test.wav");
loader.Load(fileData.get(), "test_data/1ch/44100/32/test.wav");
loader.Load(fileData.get(), "test_data/1ch/44100/24/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/32/test.wav");
//loader.Load(fileData.get(), "test_data/1ch/44100/64/test.wav");
// 2-channel wave
@ -104,6 +104,13 @@ int main(int argc, const char **argv) try
std::cout << "[Warning - Sample Rate Mismatch] - file is sampled at " << fileData->sampleRate << " and output is " << desiredSampleRate << std::endl;
}
std::vector<float> outputBuffer;
outputBuffer.reserve(fileData->samples.size());
linear_resample(44100.0 / 48000.0, fileData->samples, outputBuffer, fileData->samples.size());
std::cout << "Input Samples: " << fileData->samples.size() << std::endl;
std::cout << "Output Samples: " << outputBuffer.size() << std::endl;
// Convert mono to stereo for testing playback
if (fileData->channelCount == 1)
{
@ -118,6 +125,7 @@ int main(int argc, const char **argv) try
myDevice.Play(fileData->samples);
}
fileData->samples = outputBuffer;
int encoderStatus = OggOpusEncoder::WriteFile({1, PCM_FLT, DITHER_NONE}, fileData.get(), "encoded.opus");
std::cout << "Encoder Status: " << encoderStatus << std::endl;

@ -33,32 +33,55 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace nqr
{
enum EncoderError
{
NoError,
InsufficientSampleData,
FileIOError,
UnsupportedSamplerate,
UnsupportedChannelConfiguration,
UnsupportedBitdepth,
UnsupportedChannelMix,
BufferTooBig,
};
static inline void linear_resample(const double rate, const std::vector<float> & input, std::vector<float> & output, size_t samplesToProcess)
{
float * source = const_cast<float *>(input.data());
double virtualReadIndex = 0;
// Linear Interpolate
int n = samplesToProcess - 1;
while (n--)
{
unsigned readIndex = static_cast<unsigned>(virtualReadIndex);
double interpolationFactor = virtualReadIndex - readIndex;
double sample1 = source[readIndex];
double sample2 = source[readIndex + 1];
double sample = (1.0 - interpolationFactor) * sample1 + interpolationFactor * sample2;
output.push_back(sample);
virtualReadIndex += rate;
}
}
enum EncoderError
{
NoError,
InsufficientSampleData,
FileIOError,
UnsupportedSamplerate,
UnsupportedChannelConfiguration,
UnsupportedBitdepth,
UnsupportedChannelMix,
BufferTooBig,
};
// A simplistic encoder that takes a blob of data, conforms it to the user's
// EncoderParams preference, and writes to disk. Be warned, does not support resampling!
// @todo support dithering, samplerate conversion, etc.
struct WavEncoder
{
// Assume data adheres to EncoderParams, except for bit depth and fmt
static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path);
};
// A simplistic encoder that takes a blob of data, conforms it to the user's
// EncoderParams preference, and writes to disk. Be warned, does not support resampling!
// @todo support dithering, samplerate conversion, etc.
struct WavEncoder
{
// Assume data adheres to EncoderParams, except for bit depth and fmt
static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path);
};
struct OggOpusEncoder
{
static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path);
};
struct OggOpusEncoder
{
static int WriteFile(const EncoderParams p, const AudioData * d, const std::string & path);
};
} // end namespace nqr

@ -450,4 +450,4 @@ int OggOpusEncoder::WriteFile(const EncoderParams p, const AudioData * d, const
return EncoderError::NoError;
}
#undef OPUS_MAX_PACKET_SIZE
#undef OPUS_MAX_PACKET_SIZE
Loading…
Cancel
Save