objective-C:为什么我的循环没有终止?

时间:2016-01-14 06:40:40

标签: ios objective-c avfoundation

我正在编写一个带有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

4 个答案:

答案 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)

原因:您的条件变量readPointunsigned整数,这意味着它不能具有负值。条件readPoint > 0将始终为真,从而导致无限循环。您应该使用简单的intSInt64NSInteger来支持负值。

答案 3 :(得分:0)

在循环中使用无符号类型很好,但是你需要确保它不会变为负数,因为这意味着它会读取比可用数据更多的数据。

这可以通过以下方式解决:

UInt32 bytesToRead = MIN(readPoint, 2);

或:

while (readPoint >= 2)

取决于您是否要允许奇数编号。