Пытаюсь научиться обрабатывать записанный с микрофона звук, нашёл пример, но там всё склеено, и непонятно что за что отвечает.
Мне нужно
Записать допустим 3 секунды
Получить доступ к массиву с записанными данными, проанализировать или даже изменить
Проиграть запись, сохранённую в массиве
Вот пример, о котором писал.
//#include <unistd.h>
#include <AL/al.h>
#include <AL/alc.h>
#include <time.h>
#include <ctime>
#pragma comment (lib,"OpenAL32.lib")
#include <iostream>
#include <stdio.h>
//#include <windows.h>
//#include <al.h>
//#include <alc.h>
using namespace std;
int main()
{
ALCdevice *dev[2];
ALCcontext *ctx;
ALuint source, buffers[3];
char data[5000];
ALuint buf;
ALint val;
float ttotal;
unsigned int ccount;
long int c1ount;
c1ount =0;
dev[0] = alcOpenDevice(NULL);
ctx = alcCreateContext(dev[0], NULL);
alcMakeContextCurrent(ctx);
alGenSources(1, &source);
alGenBuffers(3, buffers);
/* Setup some initial silent data to play out of the source */
alBufferData(buffers[0], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alBufferData(buffers[1], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alBufferData(buffers[2], AL_FORMAT_MONO16, data, sizeof(data), 22050);
alSourceQueueBuffers(source, 3, buffers);
/* If you don't need 3D spatialization, this should help processing time */
alDistanceModel(AL_NONE);
dev[1] = alcCaptureOpenDevice(NULL, 22050, AL_FORMAT_MONO16, sizeof(data)/2); //22050 mean 22.050 samples per second. or 44100 for 44.1 per second.
/* Start playback and capture, and enter the audio loop */
alSourcePlay(source);
alcCaptureStart(dev[1]); //starts ring buffer
while(1)
{
/* Check if any queued buffers are finished */
alGetSourcei(source, AL_BUFFERS_PROCESSED, &val);
if(val <= 0)
continue;
/* Check how much audio data has been captured (note that 'val' is the
* number of frames, not bytes) */
alcGetIntegerv(dev[1], ALC_CAPTURE_SAMPLES, 1, &val);
/* Read the captured audio */
alcCaptureSamples(dev[1], data, val);
//***** Process/filter captured data here *****//
c1ount = c1ount +1;
if(c1ount >= 33){
break;
}
//for (int ii=0;ii<val;++ii) {
// data[ii]*=0.1; // Make it quieter
//}
//***** end Process/filter captured data here *****//
/* Pop the oldest finished buffer, fill it with the new capture data,
then re-queue it to play on the source */
alSourceUnqueueBuffers(source, 1, &buf);
alBufferData(buf, AL_FORMAT_MONO16, data, val*2 /* bytes here, not
frames */, 22050);
alSourceQueueBuffers(source, 1, &buf);
/* Make sure the source is still playing */
alGetSourcei(source, AL_SOURCE_STATE, &val);
if(val != AL_PLAYING)
{
alSourcePlay(source);
}
}
cout<< "fgggggggg\n";
/* Shutdown and cleanup */
alcCaptureStop(dev[1]);
alcCaptureCloseDevice(dev[1]);
alSourceStop(source);
alDeleteSources(1, &source);
alDeleteBuffers(3, buffers);
alDeleteBuffers(1, &buf);
alcMakeContextCurrent(NULL);
alcDestroyContext(ctx);
alcCloseDevice(dev[0]);
return 0;
}
Вот тоже пример, который должен записывать, но почему тут вечный цикл?
#include <AL/al.h>
#include <AL/alc.h>
#include <iostream>
using namespace std;
#pragma comment(lib,"OpenAL32.lib")
const int SRATE = 44100;
const int SSIZE = 1024;
ALbyte buffer[22050];
ALint sample;
int main(int argc, char *argv[]) {
alGetError();
ALCdevice *device = alcCaptureOpenDevice(NULL, SRATE, AL_FORMAT_STEREO16, SSIZE);
if (alGetError() != AL_NO_ERROR) {
return 0;
}
alcCaptureStart(device);
while (true) {
alcGetIntegerv(device, ALC_CAPTURE_SAMPLES, (ALCsizei)sizeof(ALint), &sample);
alcCaptureSamples(device, (ALCvoid *)buffer, sample);
// ... do something with the buffer
for(int i = 0; i<80;i++)
{
cout<<(int)buffer[i]<<' ';
}
cout<<"loop s\n";
}
alcCaptureStop(device);
alcCaptureCloseDevice(device);
return 0;
}
В первом примере вот эта строка сохраняет данные аудио в массив data:
alcCaptureSamples(dev[1], data, val);
Длительность звука в массиве рассчитывается по формуле
t = (N Samples) / (SampleRate * N Channels)
Размер данных в массиве (в байтах) рассчитывается по формуле:
N Bytes = N Samples * (BitsPerSample / 8)
У вас N Channels = 1 (моно), SampleRate = 22050, BitsPerSample = 16, получаем:
t = val / 22050;
N_bytes = val * 2;
Вам нужно объявить массив, размером достаточный для хранения требуемой длительности аудио, допустим, saved_data. После получения каждой порции через alcCaptureSamples накапливаете данные в этом массиве (просто через memcpy копируете в конец массива и сохраняете суммарный размер). Когда длительность достигает требуемого значения, останавливаете цикл, делаете свою обработку, а потом массив с накопленными данными передаете в alBufferData и выполняете код воспроизведения:
alSourceUnqueueBuffers(source, 1, &buf);
alBufferData(buf, AL_FORMAT_MONO16, saved_data, N_bytes, 22050);
alSourceQueueBuffers(source, 1, &buf);
Есть вот такой пример записи звука на чистом WASAPI, возможно будет полезен. Правда, там сохранение сразу в файл сделано, а не в массив.
Виртуальный выделенный сервер (VDS) становится отличным выбором
Нужно записать слово "Hello" во все файлы с расширениемtxt по указанному пути
Изучаю JavaВ литературе и на многих ресурсах пишется, что использование буферезированного ввода данных является наиболее эффективным, с точки...