Annoying tick with speex

I am making an application in which I use Speex, OpenAL and linsndfile.

The problem is that when I write a sample buffer in a file (raw pcm unsigned 16) using libsndfile, everything is correct. But if I encode them and then decode them using Spexx, I get a “tick” between each sample. At first I noticed that the sample loss or some buffer is too large. But I didn’t find anything. At first, the code was in architecture with boost streams and was divided into several classes. Even with this minimal code, my problem is still.

Here is the complete minimal code that poses the problem. Thanks for the help.

#include <iostream> #include <stdexcept> #include <vector> #include <cstring> #include <algorithm> #include <sndfile.h> #include <AL/al.h> #include <AL/alc.h> #include <speex/speex.h> typedef std::vector<ALshort> Samples; std::string chooseDevice() { std::vector<std::string> ret; const ALCchar* DeviceList = alcGetString(NULL, ALC_CAPTURE_DEVICE_SPECIFIER); int i = 0; if (DeviceList) while (strlen(DeviceList) > 0) { std::string tmp = DeviceList; ret.push_back(tmp); DeviceList += strlen(DeviceList) + 1; std::cout << i++ << ": " << tmp << std::endl; } std::cout << "Choose a device : " << std::flush; if (!(std::cin >> i)) throw std::runtime_error("NaN"); return ret[i]; } SNDFILE* openFile() { SNDFILE* file; SF_INFO fileInfo; fileInfo.channels = 1; fileInfo.samplerate = 8000; fileInfo.format = SF_FORMAT_PCM_16 | SF_FORMAT_WAV; file = sf_open("capture.wav", SFM_WRITE, &fileInfo); if (!file) throw std::runtime_error("SNDFILE error"); return file; } enum Mode {DIRECT = 1, ENCODE_AND_DECODE}; void writeToFile(SNDFILE* file, const Samples& samples, const Mode mode) { static std::vector<ALshort> buffer; switch (mode) { case DIRECT: sf_write_short(file, &samples[0], samples.size()); break; // Ecriture ici case ENCODE_AND_DECODE: { std::copy(samples.begin(), samples.end(), std::back_inserter(buffer)); int frameSize; void* encoderState = speex_encoder_init(&speex_wb_mode); speex_encoder_ctl(encoderState, SPEEX_GET_FRAME_SIZE, &frameSize); // AL pourrait donner trop ou pas assez d'échantillons while (buffer.size() >= frameSize) { // encodage void* encoderState = speex_encoder_init(&speex_wb_mode); SpeexBits bits; speex_encoder_ctl(encoderState, SPEEX_GET_FRAME_SIZE, &frameSize); buffer.reserve(2*frameSize); std::vector<char> output; output.resize(2*frameSize); speex_bits_init(&bits); speex_encode_int(encoderState, &buffer[0], &bits); int bytes = speex_bits_write(&bits, &output[0], output.size()); speex_bits_destroy(&bits); speex_encoder_destroy(encoderState); // décodage speex_bits_init(&bits); encoderState = speex_decoder_init(&speex_wb_mode); speex_encoder_ctl(encoderState, SPEEX_GET_FRAME_SIZE, &frameSize); speex_bits_read_from(&bits, &output[0], bytes); std::vector<short> samples(frameSize); speex_decode_int(encoderState, &bits, &samples[0]); sf_write_short(file, &samples[0], frameSize); // Ecriture ici speex_decoder_destroy(encoderState); speex_bits_destroy(&bits); buffer.erase(buffer.begin(), buffer.begin()+frameSize); std::cout << "." << std::flush; } } break; } } void closeFile(SNDFILE* file) { sf_close(file); std::cout << "enregistré dans capture.wav" << std::endl; } int main() { ALCdevice* device; ALCdevice* captureDevice; ALCcontext* context; device = alcOpenDevice(0); if (!device) throw std::runtime_error("Unable to open the AL device"); context = alcCreateContext(device, 0); if (!context) throw std::runtime_error("Unable to create AL context"); if (!alcMakeContextCurrent(context)) throw std::runtime_error("Unable to set the context"); if (alcIsExtensionPresent(device, "ALC_EXT_CAPTURE") == AL_FALSE) throw std::runtime_error("AL Capture extension not available"); captureDevice = alcCaptureOpenDevice(chooseDevice().c_str(), 8000, AL_FORMAT_MONO16, 8000); if (!captureDevice) throw std::runtime_error("Unable to open the capture device"); Samples samples; SNDFILE* file = openFile(); std::cout << "Mode direct (1) ou encodage et décodage ? (2) : " << std::endl; int i; std::cin >> i; Mode mode = Mode(i); time_t start = time(0); alcCaptureStart(captureDevice); while (time(0) - start < 5) { ALCint availableSamples; alcGetIntegerv(captureDevice, ALC_CAPTURE_SAMPLES, 1, &availableSamples); if (availableSamples > 0) { samples.resize(availableSamples); alcCaptureSamples(captureDevice, &samples[0], availableSamples); writeToFile(file, samples, mode); } } alcCaptureStop(captureDevice); closeFile(file); alcCaptureCloseDevice(captureDevice); alcMakeContextCurrent(0); alcDestroyContext(context); alcCloseDevice(device); } 

-lspeex -lsndfile -lopenal

+2
source share
1 answer

Well, let’s say so, if you did not need to maintain the same state for all decoded frames, there would first be no state object.

0
source

Source: https://habr.com/ru/post/989455/


All Articles