之前寫過一片文章“IOS中使用SoundTouch庫實現變聲”。
最後有很多朋友在部落格上說發出來的代碼在模擬器上運行可以,不能在真機上運行,前段時間一直也很忙,2013好看的美劇熱門排行榜沒時間翻代碼出來查看,望諒解。
今天抽空檢查了一下問題的根源,並且在IPhone 4(ios5.0.1)上測試通過,下面更新一些代碼。
同樣是Apple官方的SpeakHere,要下載代碼的,請查看上一篇文章。
- void AQRecorder::StartRecord(CFStringRef inRecordFile)
- {
- mSoundTouch.setSampleRate(44100);//mRecordFormat.mSampleRate
- mSoundTouch.setChannels(1);//mRecordFormat.mChannelsPerFrame
- mSoundTouch.setTempoChange(1.0);
- mSoundTouch.setPitchSemiTones(9);
- mSoundTouch.setRateChange(-0.7);
-
- mSoundTouch.setSetting(SETTING_SEQUENCE_MS, 40);
- mSoundTouch.setSetting(SETTING_SEEKWINDOW_MS, 16);
- mSoundTouch.setSetting(SETTING_OVERLAP_MS, 8);
-
- //Only use one of the following two options
- // mSoundTouch.setSetting(SETTING_USE_QUICKSEEK, 0);
- // mSoundTouch.setSetting(SETTING_USE_AA_FILTER, !(0));
- // mSoundTouch.setSetting(SETTING_AA_FILTER_LENGTH, 32);
紅色的兩行很重要,需要指明採樣率和聲道。如果需要使用後面注釋兩個變數,需要在SetupAudioFormat方法執行之後才可以,否則無效,原因大家都懂的。
將麥克風捕捉的聲音回呼函數按照一下代碼更新。
- // ____________________________________________________________________________________
- // AudioQueue callback function, called when an input buffers has been filled.
- void AQRecorder::MyInputBufferHandler( void * inUserData,
- AudioQueueRef inAQ,
- AudioQueueBufferRef inBuffer,
- const AudioTimeStamp * inStartTime,
- UInt32 inNumPackets,
- const AudioStreamPacketDescription* inPacketDesc)
- {
-
- AQRecorder *aqr = (AQRecorder *)inUserData;
- try {
- if (inNumPackets > 0) {
- UInt32 audioDataByteSize = inBuffer->mAudioDataByteSize;
- CAStreamBasicDescription queueFormat = aqr->DataFormat();
- SoundTouch *soundTouch = aqr->GetSoundTouch();
-
- uint nSamples = audioDataByteSize/queueFormat.mBytesPerPacket;
- soundTouch->putSamples((const SAMPLETYPE *)inBuffer->mAudioData,nSamples);
-
- SAMPLETYPE *samples = (SAMPLETYPE *)malloc(audioDataByteSize);
- UInt32 numSamples;
- do {
- memset(samples, 0, audioDataByteSize);
- numSamples = soundTouch->receiveSamples((SAMPLETYPE *)samples, nSamples);
- // write packets to file
- XThrowIfError(AudioFileWritePackets(aqr->mRecordFile,
- FALSE,
- numSamples*queueFormat.mBytesPerPacket,
- NULL,
- aqr->mRecordPacket,
- &numSamples,
- samples),
- "AudioFileWritePackets failed");
- aqr->mRecordPacket += numSamples;
- } while (numSamples!=0);
- free(samples);
- }
-
- // if we're not stopping, re-enqueue the buffe so that it gets filled again
- if (aqr->IsRunning())
- XThrowIfError(AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, NULL), "AudioQueueEnqueueBuffer failed");
- } catch (CAXException e) {
- char buf[256];
- fprintf(stderr, "Error: %s (%s)\n", e.mOperation, e.FormatError(buf));
- }
- }
原因大家自己應該能看明白。
之前是在xcode 3.x上寫的代碼,剛開始有朋友反饋時,我以為是版本問題產生的,結果不是神奇影院.
本次更新的代碼是我在xcode4.2和iphone4上測試無誤的,如果還有問題的,可以仔細看看前後兩篇文章。不要吧參數設定錯誤了。
ps:QQ經常不線上,有問題上微博:http://weibo.com/yarin
本文出自 “yarin's blog” 部落格,請務必保留此出處http://yarin.blog.51cto.com/1130898/794768