Как записать микрофон, пока нет звука?

Я создал 2 функции:
— тот, который записывает микрофон
— тот, который играет звук микрофона

Записывает микрофон за 3 секунды

#include <iostream>
#include <Windows.h>
#include <vector>
using namespace std;

#pragma comment(lib, "winmm.lib")

short int waveIn[44100 * 3];

void PlayRecord();

void StartRecord()
{
const int NUMPTS = 44100 * 3;   // 3 seconds
int sampleRate = 44100;
// 'short int' is a 16-bit type; I request 16-bit samples below
// for 8-bit capture, you'd use 'unsigned char' or 'BYTE' 8-bit     types

HWAVEIN      hWaveIn;
MMRESULT result;

WAVEFORMATEX pFormat;
pFormat.wFormatTag=WAVE_FORMAT_PCM;     // simple, uncompressed format
pFormat.nChannels=1;                    //  1=mono, 2=stereo
pFormat.nSamplesPerSec=sampleRate;      // 44100
pFormat.nAvgBytesPerSec=sampleRate*2;   // = nSamplesPerSec * n.Channels *    wBitsPerSample/8
pFormat.nBlockAlign=2;                  // = n.Channels * wBitsPerSample/8
pFormat.wBitsPerSample=16;              //  16 for high quality, 8 for telephone-grade
pFormat.cbSize=0;

// Specify recording parameters

result = waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat,
0L, 0L, WAVE_FORMAT_DIRECT);

WAVEHDR      WaveInHdr;
// Set up and prepare header for input
WaveInHdr.lpData = (LPSTR)waveIn;
WaveInHdr.dwBufferLength = NUMPTS*2;
WaveInHdr.dwBytesRecorded=0;
WaveInHdr.dwUser = 0L;
WaveInHdr.dwFlags = 0L;
WaveInHdr.dwLoops = 0L;
waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

// Insert a wave input buffer
result = waveInAddBuffer(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));// Commence sampling input
result = waveInStart(hWaveIn);cout << "recording..." << endl;

Sleep(3 * 1000);
// Wait until finished recording

waveInClose(hWaveIn);

PlayRecord();
}

void PlayRecord()
{
const int NUMPTS = 44100 * 3;   // 3 seconds
int sampleRate = 44100;
// 'short int' is a 16-bit type; I request 16-bit samples below
// for 8-bit capture, you'd    use 'unsigned char' or 'BYTE' 8-bit types

HWAVEIN  hWaveIn;

WAVEFORMATEX pFormat;
pFormat.wFormatTag=WAVE_FORMAT_PCM;     // simple, uncompressed format
pFormat.nChannels=1;                    //  1=mono, 2=stereo
pFormat.nSamplesPerSec=sampleRate;      // 44100
pFormat.nAvgBytesPerSec=sampleRate*2;   // = nSamplesPerSec * n.Channels * wBitsPerSample/8
pFormat.nBlockAlign=2;                  // = n.Channels * wBitsPerSample/8
pFormat.wBitsPerSample=16;              //  16 for high quality, 8 for telephone-grade
pFormat.cbSize=0;

// Specify recording parameters

waveInOpen(&hWaveIn, WAVE_MAPPER,&pFormat, 0L, 0L, WAVE_FORMAT_DIRECT);

WAVEHDR      WaveInHdr;
// Set up and prepare header for input
WaveInHdr.lpData = (LPSTR)waveIn;
WaveInHdr.dwBufferLength = NUMPTS*2;
WaveInHdr.dwBytesRecorded=0;
WaveInHdr.dwUser = 0L;
WaveInHdr.dwFlags = 0L;
WaveInHdr.dwLoops = 0L;
waveInPrepareHeader(hWaveIn, &WaveInHdr, sizeof(WAVEHDR));

HWAVEOUT hWaveOut;
cout << "playing..." << endl;
waveOutOpen(&hWaveOut, WAVE_MAPPER, &pFormat, 0, 0, WAVE_FORMAT_DIRECT);
waveOutWrite(hWaveOut, &WaveInHdr, sizeof(WaveInHdr)); // Playing the data
Sleep(3 * 1000); //Sleep for as long as there was recorded

waveInClose(hWaveIn);
waveOutClose(hWaveOut);
}

int main()
{
StartRecord();
return 0;
}

Как я могу изменить свою функцию StartRecord (и я полагаю, что и моя функция PlayRecord), чтобы она записывалась до тех пор, пока не поступит сигнал от микрофона?

(Пока что эти две функции работают отлично — записывает микрофон в течение 3 секунд, затем воспроизводит запись) …

Спасибо!

Изменить: под звуком я имею в виду, что уровень звука слишком низкий или что-то в этом роде (значит, человек, вероятно, не говорит) …

3

Решение

Поскольку звук — это волна, он колеблется между высоким и низким давлением. Эта форма волны обычно записывается как положительные и отрицательные числа, при этом нулевое давление является нейтральным давлением. Если вы берете абсолютное значение сигнала и сохраняете скользящее среднее, этого должно быть достаточно.

Среднее значение следует принимать в течение достаточно длительного периода, чтобы вы учитывали соответствующее количество тишины. Очень дешевый способ сохранить оценку скользящего среднего:

const double threshold = 50;    // Whatever threshold you need
const int max_samples = 10000;  // The representative running average size

double average = 0;             // The running average
int sample_count = 0;           // When we are building the average

while( sample_count < max_samples || average > threshold ) {
// New sample arrives, stored in 'sample'

// Adjust the running absolute average
if( sample_count < max_samples ) sample_count++;
average *= double(sample_count-1) / sample_count;
average += std::abs(sample) / sample_count;
}

Чем больше max_samplesчем медленнее average ответит на сигнал. После того, как звук прекратится, он медленно затихнет. Тем не менее, он будет медленно расти снова. Это было бы хорошо для достаточно непрерывного звука.

С чем-то вроде речи, которая может иметь короткие или длинные паузы, вы можете использовать импульсный подход. Вы можете просто определить ожидаемое количество сэмплов «тишины» и сбрасывать его всякий раз, когда вы получаете импульс, превышающий пороговое значение. Использование приведенного выше скользящего среднего с гораздо более коротким размером окна даст вам простой способ обнаружения импульса. Тогда вам просто нужно посчитать …

const int max_samples = 100;             // Smaller window size for impulse
const int max_silence_samples = 10000;   // Maximum samples below threshold
int silence = 0;                         // Number of samples below threshold

while( silence < max_silence_samples ) {
// Compute running average as before

//...

// Check for silence.  If there's a signal, reset the counter.
if( average > threshold ) silence = 0;
else ++silence;
}

регулировка threshold а также max_samples будет контролировать чувствительность к щелчкам и щелчкам, а max_silence_samples дает вам контроль над тем, сколько тишины разрешено, прежде чем остановить запись.

Есть, несомненно, более технические способы для достижения ваших целей, но всегда хорошо сначала попробовать простой. Посмотрите, как вы идете с этим.

5

Другие решения

Я предлагаю вам сделать это через DirectShow. Вы должны создать экземпляр микрофона, SampleGrabber, аудиокодера и средства записи файлов. Ваш график должен быть таким:

Микрофон -> SampleGrabber -> Аудиокодер -> File Writer

Каждый семпл проходит через SampleGrabber, и вы можете прочитать все необработанные семплы и проверить, следует ли вам продолжить запись или нет. Это лучший способ записать и проверить его содержимое.

0

По вопросам рекламы [email protected]