2016-01-14 9 views
0

Я пишу быстрое приложение с функцией объектива-С, чтобы перевернуть аудиофайл. Я очень новичок в Objective-C, и у меня возникает проблема с остановкой моего цикла, даже когда моя переменная readPoint становится отрицательной. Как остановить этот цикл, когда он достигнет нуля?Цель-C: Почему моя петля не заканчивается?

#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

положить перерыв; заявление на разрыв цикла. –

+0

Благодарим вас за ответ. Где бы я разместил перерыв? ? – Derek

+0

@AvijitNagare 'while (readPoint> 0)' достаточно для завершения цикла, когда «readPoint - = 2» принимает значение в отрицательное, добавление оператора «if» просто вводит избыточность в код. не нужно дополнительно проверять. Я бы посмотрел на ответ Гэндальфса ниже. –

ответ

1

Вы используете неподписанный переменную целого типа и положить чек, если он идет в сторону отрицательных значений или нет (readPoint> 0), что не является правильным. Вам нужно Подпись Int, чтобы иметь возможность сделать такое сравнение. Используйте этот код

SInt64 readPoint = dataSize; 
+1

Если 'readPoint' становится отрицательным, то он читает больше данных, чем должно быть.Подписание подписки не останавливает эту проблему. – trojanfoe

+0

@trojanfoe Я думаю, что это остановит его, поскольку условие будет терпеть неудачу в случае Signed Int. Я признаю, что я не учитывал общую картину и просто ответил на вопрос «почему его петля не ломалась». Вот почему я предложил ему заглянуть в ответ Курта Ревиса. – Gandalf

1

Каждый раз через петлю, вы запрашиваете, что AudioFileReadBytes() следует читать 2 байта. Он устанавливает bytesToRead в объем данных, которые он действительно читает.

Представьте, что начинается с 1. Вы запрашиваете 2 байта, но AudioFileReadBytes дает вам только 1, потому что это все, что осталось в файле. Затем вы уменьшаете на 2, а так как он без знака, он обертывается до огромного положительного целого числа, и ваш цикл не выходит.

Вы должны уменьшить на сумму, которая была фактически прочитана.

(Вы не нужно сделать знаковое значение, которое только покрывает тот факт, что вы делаете математику неправильно Если 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; 
} 
0

Причины: Ваша условная переменная является unsigned целого числа, которое означает, что он не может иметь отрицательное значение. Условие readPoint > 0 всегда будет истинным и, следовательно, приведет к бесконечному циклу. Вы должны использовать простые int, SInt64 или NSInteger, чтобы поддерживать отрицательные значения.

+0

Что делать, если 'readPoint' равно 0? –

+0

Поскольку 'UInt64 readPoint = dataSize;' dataSize может быть нечетным значением, это то, что 'readPoint' никогда не равен нулю, и цикл продолжается. – Nishant

0

Использование неподписанного типа в порядке, но вам нужно убедиться, что он не идет отрицательным, поскольку это означает, что он читает больше данных, чем доступно.

Это решается просто с:

UInt32 bytesToRead = MIN(readPoint, 2); 

или:

while (readPoint >= 2) 

в зависимости от того, хотите ли вы, чтобы нечетные размеры.

Смежные вопросы