如何在使用audioFileWritePackets创建的新文件上设置持续时间?

时间:2014-12-31 17:23:15

标签: ios objective-c xcode

我使用AudioFileReadPacketData连接了​​2个音频文件,以读取现有文件并使用AudioFileWritePackets将数据写入第三个文件。源文件似乎包含有关其持续时间的信息。我可以使用下面的代码访问它,传递文件url

-(float)lengthForUrl:(NSURL *)url
{
AVURLAsset* audioAsset = [AVURLAsset URLAssetWithURL:url options:nil];
CMTime audioDuration = audioAsset.duration;
float audioDurationSeconds = CMTimeGetSeconds(audioDuration);
return audioDurationSeconds;
}

当我对我的新组合文件进行相同的调用时,我的持续时间为0。

如何设置新文件的持续时间? 或者在转移过程中保留它?

1 个答案:

答案 0 :(得分:0)

我没弄明白如何在我的合并文件中设置持续时间,但确实如此 弄清楚如何在持续时间不变的情况下创建它。 我从使用AssetReader / Writer切换到使用ExtFileReader / Writer - 工作代码在

之下
- (BOOL)combineFilesFor:(NSURL*)url
{

dispatch_async(dispatch_get_main_queue(), ^{
    activity.hidden = NO;
    [activity startAnimating];
});

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,        NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *soundOneNew = [documentsDirectory stringByAppendingPathComponent:Kcombined];
NSLog(@"%@",masterUrl);
NSLog(@"%@",url);
// create the url for the combined file
CFURLRef out_url = (__bridge CFURLRef)[NSURL fileURLWithPath:soundOneNew];
NSLog(@"out file url : %@", out_url);
ExtAudioFileRef af_in;
ExtAudioFileRef af_out = NULL;
Float64 existing_audioDurationSeconds = [self lengthForUrl:masterUrl];
NSLog(@"duration of existing file : %f", existing_audioDurationSeconds);
Float64 new_audioDurationSeconds = [self lengthForUrl:url];
NSLog(@"duration of existing file : %f", new_audioDurationSeconds);
Float64 combined_audioDurationSeconds = existing_audioDurationSeconds + new_audioDurationSeconds;
NSLog(@"duration of combined : %f", combined_audioDurationSeconds);
// put the urls of the files to combine in to an array
NSArray *sourceURLs = [NSArray arrayWithObjects:(__bridge id)((__bridge CFURLRef) 
AudioStreamBasicDescription         inputFileFormat;
AudioStreamBasicDescription         converterFormat;
UInt32                              thePropertySize = sizeof(inputFileFormat);
AudioStreamBasicDescription         outputFileFormat;
#define BUFFER_SIZE 4096
UInt8 *buffer = NULL;
for (id in_url in sourceURLs) {
    NSLog(@"url in = %@",in_url);
    OSStatus in_stat = ExtAudioFileOpenURL ( (__bridge CFURLRef)(in_url), &af_in);
    NSLog(@"in file open status : %d", (int)in_stat);

    bzero(&inputFileFormat, sizeof(inputFileFormat));
    in_stat = ExtAudioFileGetProperty(af_in, kExtAudioFileProperty_FileDataFormat,
                                      &thePropertySize, &inputFileFormat);
    NSLog(@"in file get property status : %d", (int)in_stat);
    memset(&converterFormat, 0, sizeof(converterFormat));
    converterFormat.mFormatID = kAudioFormatLinearPCM;
    converterFormat.mSampleRate = inputFileFormat.mSampleRate;
    converterFormat.mChannelsPerFrame = 1;
    converterFormat.mBytesPerPacket = 2;
    converterFormat.mFramesPerPacket = 1;
    converterFormat.mBytesPerFrame = 2;
    converterFormat.mBitsPerChannel = 16;
    converterFormat.mFormatFlags = kAudioFormatFlagsNativeEndian |kAudioFormatFlagIsPacked | kAudioFormatFlagIsSignedInteger;


    in_stat = ExtAudioFileSetProperty(af_in, kExtAudioFileProperty_ClientDataFormat,
                                  sizeof(converterFormat), &converterFormat);
    NSLog(@"in file set property status : %d", (int)in_stat);

    if (af_out == NULL) {
        memset(&outputFileFormat, 0, sizeof(outputFileFormat));
        outputFileFormat.mFormatID = kAudioFormatMPEG4AAC;
        outputFileFormat.mFormatFlags = kMPEG4Object_AAC_Main;
        outputFileFormat.mSampleRate = inputFileFormat.mSampleRate;
        outputFileFormat.mChannelsPerFrame = inputFileFormat.mChannelsPerFrame;
        // create the new file to write the combined file 2
        OSStatus out_stat = ExtAudioFileCreateWithURL(out_url, kAudioFileM4AType, &outputFileFormat,
                                                      NULL, kAudioFileFlags_EraseFile, &af_out);
        NSLog(@"out file create status : %d", out_stat);
        out_stat = ExtAudioFileSetProperty(af_out, kExtAudioFileProperty_ClientDataFormat,
                                      sizeof(converterFormat), &converterFormat);
        NSLog(@"out file set property status : %d", out_stat);

    }
    // Buffer to read from source file and write to dest file
    buffer = malloc(BUFFER_SIZE);
    assert(buffer);

    AudioBufferList conversionBuffer;
    conversionBuffer.mNumberBuffers = 1;
    conversionBuffer.mBuffers[0].mNumberChannels = inputFileFormat.mChannelsPerFrame;
    conversionBuffer.mBuffers[0].mData = buffer;
    conversionBuffer.mBuffers[0].mDataByteSize = BUFFER_SIZE;

    while (TRUE) {
        conversionBuffer.mBuffers[0].mDataByteSize = BUFFER_SIZE;

        UInt32 frameCount = INT_MAX;

        if (inputFileFormat.mBytesPerFrame > 0) {
            frameCount = (conversionBuffer.mBuffers[0].mDataByteSize / inputFileFormat.mBytesPerFrame);
        }

        // Read a chunk of input

        OSStatus err = ExtAudioFileRead(af_in, &frameCount, &conversionBuffer);

        if (err) {
             NSLog(@"error read from input file : %d", (int)err);
        }else{
            NSLog(@"read %d frames from inout file", frameCount);
        }

        // If no frames were returned, conversion is finished

        if (frameCount == 0)
            break;

        // Write pcm data to output file

        err = ExtAudioFileWrite(af_out, frameCount, &conversionBuffer);

        if (err) {
            NSLog(@"error write out file : %d", (int)err);
        }else{
            NSLog(@"wrote %d frames to out file", frameCount);
        }
    }
    ExtAudioFileDispose(af_in);
}
ExtAudioFileDispose (af_out);
NSLog(@"combined file duration =: %f", [self lengthForUrl:[NSURL fileURLWithPath:soundOneNew]]);
// move the new file into place
[self deleteFileWithName:KUpdate forType:@""];
[self deleteFileWithName:KMaster forType:@""];
player = nil;
[self replaceFileAtPath:KMaster withData:[NSData dataWithContentsOfFile:soundOneNew]];
[self deleteFileWithName:Kcombined forType:@""];

[self pauseRecording];

dispatch_async(dispatch_get_main_queue(), ^{
    activity.hidden = YES;
    [activity stopAnimating];
    record.enabled = YES;
});

return YES;
}