2014-02-14 39 views
2

我創建了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功能也一樣),要記錄直到沒有來自麥克風的輸入?

(到目前爲止,那些2個功能被完美的工作 - 記錄3秒的麥克風,然後播放錄音)...

謝謝!

編輯:由沒有聲音,我的意思是音量太低或某事(指可能心不是說話的人)......

+1

沒有「沒有聲音」之類的東西。相反,在一段時間內,聲音水平會降低到某個閾值以下。 –

+0

那就是我的意思。那麼如何檢查聲級? – Amit

+0

[試圖編寫通過WinAPI錄製和播放聲音的函數]的可能重複(http://stackoverflow.com/questions/21741194/trying-to-write-functions-that-record-and-play-sound-through- winapi)由同一張海報。 –

回答

4

由於聲音是一個波,它在高低壓之間振盪。該波形通常記錄爲正數和負數,零是中性壓力。如果你拿到信號的絕對值並保持平均值,那應該就足夠了。

平均值應該花費足夠長的時間,以保證適當的沉默量。保持運行平均的估值非常便宜的方法是這樣的:

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; 
} 

調整thresholdmax_samples將控制持久性有機污染物和點擊的敏感性,而max_silence_samples讓您對您停止錄製之前多少沉默允許控制。

毫無疑問,有更多技術方法可以實現您的目標,但首先嚐試簡單的方法總是很好的。看看你如何去與此。

0

我建議你通過DirectShow的做到這一點。您應該創建一個麥克風實例,SampleGrabber,音頻編碼器和文件編寫器。您的圖形應該是這樣的:

麥克風 - > SampleGrabber - >音頻編碼器 - >文件寫入

每個樣品通過SampleGrabber,你可以閱讀所有的原始樣本,並檢查是否應該繼續記錄或不。這是記錄和檢查其內容的最佳方式。

+0

寫入文件 - >打開文件以獲取音頻並在電腦上播放會慢得多,特別是如果我想用它來進行VOIP ... – Amit

+0

這就是你的全部選擇。您可以通過默認DirectSound設備渲染它,或將其渲染爲空渲染器,或將其寫入文件等。這是您的所有選擇。我建議你寫入文件,因爲你的代碼執行此操作。 –

+0

我的代碼不寫入文件,播放函數獲取緩衝區並播放它,使它快得多... – Amit

相關問題