NSURL возвращает неверную сводку при объединении файлов WAV - PullRequest
1 голос
/ 16 декабря 2011

Я пытаюсь объединить 2 файла .wav внутри проекта Objective-C. Идея состоит в том, что я хочу, чтобы он дал такой вывод: file1 + (file2 - header). В этом случае заголовок первого файла должен быть изменен, чтобы отразить новый размер. Если первый файл пуст (поэтому только первый раз), я хочу, чтобы метод возвращал второй файл целиком, но в файле 1 URL. Прямо сейчас у меня есть:

+(NSURL *)mergeFile1:(NSURL *)file1 withFile2:(NSURL *)file2 {
    if(file1 == nil) {
        return [file2 copy];
    }

    NSData * wav1Data = [NSData dataWithContentsOfFile:[file1 absoluteString]];
    NSData * wav2Data = [NSData dataWithContentsOfFile:[file2 absoluteString]];

    int wav1DataSize = [wav1Data length] - 46;  
    int wav2DataSize = [wav2Data length] - 46;

    [NSMutableData dataWithData:[wav1Data subdataWithRange:NSMakeRange(46, wav1DataSize)]];

    if (wav1DataSize <= 0 ||  wav2DataSize <= 0) {
        return nil;
    }   

    NSMutableData * soundFileData = [NSMutableData dataWithData:[wav1Data subdataWithRange:NSMakeRange(0, 46)]];
    [soundFileData appendData:[wav1Data subdataWithRange:NSMakeRange(46, wav1DataSize)]];
    [soundFileData appendData:[wav2Data subdataWithRange:NSMakeRange(46, wav2DataSize)]];

    unsigned int totalLength = [soundFileData length];

    NSLog(@"%d", totalLength);

    [soundFileData replaceBytesInRange:NSMakeRange(4, 4) withBytes:[NSString stringWithFormat:@"%X", totalLength-8]];
    [soundFileData replaceBytesInRange:NSMakeRange(42, 4) withBytes:[NSString stringWithFormat:@"%X", totalLength]];

    [soundFileData writeToURL:file1 atomically:YES];

    return [file1 copy];
}

Я называю это так:

if(soundFileURL != nil) {
        NSURL *tempURL = [WavUtils mergeFile1:finalSoundFileURL withFile2:soundFileURL];

        if(tempURL != nil) {
            NSLog(@"Wav files have been merged.");
            finalSoundFileURL = [tempURL copy];
            [soundFileURL release];
            soundFileURL = nil;
        } else {
            NSLog(@"Wav files could not be merged.");
        }
    }

finalSoundFileURL определяется следующим образом:

   @interface class : UIViewController
        ....
        NSURL *soundFileURL;
        NSURL *finalSoundFileURL;
        ....
    }

Проблема, с которой я столкнулся сейчас, заключается в том, что tempURL вернется правильно, но когда я сделаю finalSoundFileURL = [tempURL copy];, finalSoundFileURL скажет «Неверное резюме» во время отладки. TempURL выдаст правильный URL. Я также не могу играть в WAV в URL, поэтому что-то явно не так.

У любого есть идея, что происходит, потому что я не понимаю, что происходит. Любая помощь приветствуется!

EDIT

Я сделал несколько скриншотов того, что показывает отладчик. Как показано на рисунке ниже, tempURL просто отлично: img1

finalSoundFileURL в тот же самый момент (после того, как временная копия копируется в конечную) показывает это: img2

Это большая загадка для меня. Это заставляет меня задуматься, почему это недействительно? Он был только что скопирован (так же как и его собственное пространство памяти), и никакой релиз не вызывается! Пожалуйста, поправьте меня, если я ошибаюсь.

1 Ответ

1 голос
/ 20 декабря 2011

Ваши replaceBytesInRange вызовы выглядят немного странно:

[soundFileData replaceBytesInRange:NSMakeRange(4, 4) withBytes:[NSString stringWithFormat:@"%X", totalLength-8]];
[soundFileData replaceBytesInRange:NSMakeRange(42, 4) withBytes:[NSString stringWithFormat:@"%X", totalLength]];

Это передаст указатели на NSString экземпляры для использования в качестве новых байтов.

Я думаю, что вы хотите сделатьчто-то вроде этого:

[soundFileData replaceBytesInRange:NSMakeRange(4, 4)
                         withBytes:&(UInt32){NSSwapHostIntToLittle(totalLength-8)}];
[soundFileData replaceBytesInRange:NSMakeRange(42, 4)
                         withBytes:&(UInt32){NSSwapHostIntToLittle(totalLength)}];

Теперь длина будет иметь правильные байты в порядке байтов, как указано в формате WAV.Смена байтов на little-endian, вероятно, является NOP при сборке как для симулятора iOS, так и для ARM, но, вероятно, хорошо быть явным.

...