[英]How to reverse an audio file?
我想反轉 iOS 上的現有音頻文件(例如 WAV、CAF、...)。 關於如何實現這一目標的任何建議? 開源庫?
我開發了一個示例應用程序,它記錄用戶所說的內容並向后播放。 我已經使用 CoreAudio 來實現這一點。 鏈接到應用程序代碼。
因為每個樣本的大小為 16 位(2 字節)(單通道)。 您可以通過從記錄結束開始並向后讀取將其復制到不同的緩沖區來一次加載每個樣本。 當您到達數據的開頭時,您已經反轉了數據並且播放將被反轉。
// set up output file
AudioFileID outputAudioFile;
AudioStreamBasicDescription myPCMFormat;
myPCMFormat.mSampleRate = 16000.00;
myPCMFormat.mFormatID = kAudioFormatLinearPCM ;
myPCMFormat.mFormatFlags = kAudioFormatFlagsCanonical;
myPCMFormat.mChannelsPerFrame = 1;
myPCMFormat.mFramesPerPacket = 1;
myPCMFormat.mBitsPerChannel = 16;
myPCMFormat.mBytesPerPacket = 2;
myPCMFormat.mBytesPerFrame = 2;
AudioFileCreateWithURL((__bridge CFURLRef)self.flippedAudioUrl,
kAudioFileCAFType,
&myPCMFormat,
kAudioFileFlags_EraseFile,
&outputAudioFile);
// set up input file
AudioFileID inputAudioFile;
OSStatus theErr = noErr;
UInt64 fileDataSize = 0;
AudioStreamBasicDescription theFileFormat;
UInt32 thePropertySize = sizeof(theFileFormat);
theErr = AudioFileOpenURL((__bridge CFURLRef)self.recordedAudioUrl, kAudioFileReadPermission, 0, &inputAudioFile);
thePropertySize = sizeof(fileDataSize);
theErr = AudioFileGetProperty(inputAudioFile, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize);
UInt32 dataSize = fileDataSize;
void* theData = malloc(dataSize);
//Read data into buffer
UInt32 readPoint = dataSize;
UInt32 writePoint = 0;
while( readPoint > 0 )
{
UInt32 bytesToRead = 2;
AudioFileReadBytes( inputAudioFile, false, readPoint, &bytesToRead, theData );
AudioFileWriteBytes( outputAudioFile, false, writePoint, &bytesToRead, theData );
writePoint += 2;
readPoint -= 2;
}
free(theData);
AudioFileClose(inputAudioFile);
AudioFileClose(outputAudioFile);
Kiran 在 Swift 2.2 中的回答:
let forwardAudioURL: NSURL = ... // wherever your original audio is
let reversedAudioURL: NSURL = ... // wherever you want the reversed file to go
// Load forward audio into originalAudioFile
var originalAudioFile: AudioFileID = nil
let possibleError1 = AudioFileOpenURL(forwardAudioURL,
AudioFilePermissions.ReadPermission,
0,
&originalAudioFile)
// Load the size in bytes of the original audio into originalAudioSize variable
var originalAudioSize: Int64 = 0
var propertySize: UInt32 = 8
let possibleError2 = AudioFileGetProperty(originalAudioFile,
kAudioFilePropertyAudioDataByteCount,
&propertySize,
&originalAudioSize)
if possibleError1 != 0 || possibleError2 != 0 {
// Handle errors if you want
}
// Set up file that the reversed audio will be loaded into
var reversedAudioFile: AudioFileID = nil
var format = AudioStreamBasicDescription()
format.mSampleRate = 16000
format.mFormatID = kAudioFormatLinearPCM
format.mChannelsPerFrame = 1
format.mFramesPerPacket = 1
format.mBitsPerChannel = 16
format.mBytesPerPacket = 2
format.mBytesPerFrame = 2
AudioFileCreateWithURL(reversedAudioURL,
kAudioFileCAFType,
&format,
AudioFileFlags.EraseFile,
&reversedAudioFile)
// Read data into the reversedAudioFile
var readPoint: Int64 = originalAudioSize
var writePoint: Int64 = 0
var buffer: Int16 = 0
while readPoint > 0 {
var bytesToRead: UInt32 = 2;
AudioFileReadBytes(originalAudioFile,
false,
readPoint,
&bytesToRead,
&buffer)
AudioFileWriteBytes(reversedAudioFile,
false,
writePoint,
&bytesToRead,
&buffer)
writePoint += 2
readPoint -= 2
}
AudioFileClose(originalAudioFile)
AudioFileClose(reversedAudioFile)
WAV 文件只包含原始 PCM 樣本。 如果您以相反的順序播放它們,您將獲得相反的聲音。 有關詳細信息,請參閱此問題。 (還有這個搜索)
使用libsndfile ,我能夠讀取錄制的音頻樣本。 下面的代碼片段然后顯示如何打開輸入文件,並以相反的順序寫入 output。 您應該注意,所有數據都是在內存中讀取的!
SF_INFO info_read;
info_read.format = 0;
SNDFILE* sndfilein = sf_open("my_input_file.caf", SFM_READ, &info_read);
SF_INFO info_write;
info_write.format = info.format;
info_write.channels = info.channels;
info_write.frames = info.frames;
info_write.samplerate = info.samplerate;
info_write.sections = info.sections;
info_write.seekable = info.seekable;
SNDFILE* sndfileout = sf_open("my_output_file.caf", SFM_RDWR, &info_write);
int* buf = new int[8000 * 30];
int framesRead = sf_readf_int(sndfilein, buf, info.frames);
for (int i = 0; i < info.frames; i++)
sf_writef_int(sndfileout, &buf[info.frames - i], 1);
delete[] buf;
sf_close(sndfilein);
sf_close(sndfileout);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.