1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
|
#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);
} |
Partager