我正在编写一个带有Objective-C函数的快速应用程序来反转音频文件。我是Objective-C的新手,我特别难以让我的循环停止,即使我的readPoint变量为负。如何在零点到达时停止此循环?
#import "objectFile.h"
#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>
#import <CoreAudio/CoreAudioTypes.h>
@implementation objectFile
-(void)callMethodFromObjectiveC{
NSURL *recordedAudioUrl;
NSURL *flippedAudioUrl;
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSString *savedURL=[defaults objectForKey:@"savedURL"];
NSString *reverseURL=[defaults objectForKey:@"reverseURL"];
recordedAudioUrl = [NSURL URLWithString:[savedURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog( @"url is %@", [recordedAudioUrl absoluteString]);
flippedAudioUrl = [NSURL URLWithString:[reverseURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSLog( @"url is %@", [flippedAudioUrl absoluteString]);
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)flippedAudioUrl,
kAudioFormatMPEG4AAC,
&myPCMFormat,
kAudioFileFlags_EraseFile,
&outputAudioFile);
AudioFileID inputAudioFile;
OSStatus theErr = noErr;
UInt64 fileDataSize = 0;
AudioStreamBasicDescription theFileFormat;
UInt32 thePropertySize = sizeof(theFileFormat);
theErr = AudioFileOpenURL((__bridge CFURLRef)recordedAudioUrl, kAudioFileReadPermission, 0, &inputAudioFile);
thePropertySize = sizeof(fileDataSize);
theErr = AudioFileGetProperty(inputAudioFile, kAudioFilePropertyAudioDataByteCount, &thePropertySize, &fileDataSize);
UInt64 dataSize = fileDataSize;
void* theData = malloc(dataSize);
UInt64 readPoint = dataSize;
UInt64 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);
}
@end
答案 0 :(得分:1)
您正在使用unsigned int类型变量并检查它是否转到负值(readPoint&gt; 0),这是不正确的。您需要一个Signed Int才能进行这样的比较。使用此代码
SInt64 readPoint = dataSize;
答案 1 :(得分:1)
每次循环时,您都要求AudioFileReadBytes()
读取2个字节。它将bytesToRead
设置为它实际读取的数据量。
想象一下readPoint
从1开始。你要求2个字节,但是AudioFileReadBytes
只给你1个,因为这就是文件中剩下的全部内容。然后你将readPoint
递减2,因为它是无符号的,它会回绕到一个巨大的正整数,并且你的循环不会退出。
您应该按实际读取的金额递减readPoint
。
(你不需要使readPoint
成为有符号的值。这只是掩盖了你做错了数学的事实。如果AudioFileReadBytes
一直返回数据少于你要求的数据 - 这是允许做的 - 你的数学结果最终可能会超过1。)
UInt64 readPoint = dataSize;
UInt64 writePoint = 0;
while( readPoint > 0 )
{
UInt32 bytesToRead = 2;
AudioFileReadBytes( inputAudioFile, false, readPoint, &bytesToRead, theData );
// bytesToRead is now the amount of data actually read
UInt32 bytesToWrite = bytesToRead;
AudioFileWriteBytes( outputAudioFile, false, writePoint, &bytesToWrite, theData );
// bytesToWrite is now the amount of data actually written
// NOTE: You are assuming bytesToWrite == bytesToRead, which is not necessarily true.
// You should ensure all the data is written before you read again.
// I'm leaving that up to you.
writePoint += bytesToWrite;
readPoint -= bytesToRead;
}
答案 2 :(得分:0)
原因:您的条件变量readPoint
是unsigned
整数,这意味着它不能具有负值。条件readPoint > 0
将始终为真,从而导致无限循环。您应该使用简单的int
,SInt64
或NSInteger
来支持负值。
答案 3 :(得分:0)
在循环中使用无符号类型很好,但是你需要确保它不会变为负数,因为这意味着它会读取比可用数据更多的数据。
这可以通过以下方式解决:
UInt32 bytesToRead = MIN(readPoint, 2);
或:
while (readPoint >= 2)
取决于您是否要允许奇数编号。