【问题标题】:How do I convert flac to wav on iOS?如何在 iOS 上将 flac 转换为 wav?
【发布时间】:2017-06-08 22:24:21
【问题描述】:

我有一个使用 FLAC 编码的文件,我想将其转换为 WAV。

我已将this FFMpeg lib 添加到我的项目并导入它。

我看到this answer的一些代码,但我不清楚如何使用它:

#import "avformat.h"

// Some code goes here

/*
 *   avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options)
 */
int openInputValue = avformat_open_input(&pFormatCtx, utf8FilePath, inputFormat, nil);
NSLog(@"%s - %d # openInputValue = %d", __PRETTY_FUNCTION__, __LINE__, openInputValue);

我目前在一个函数中有这个代码,它需要NSData 保存 FLAC 文件。 如果avformat_open_input 是正确的调用,我该如何设置变量?如果不是正确的调用,那是什么?

This question 似乎是重复的,但实际上并没有很好的答案。

另外请注意,我不想要玩家。这个文件包含 MQA,所以我需要通过我自己的自定义解码器来运行它。

【问题讨论】:

    标签: ios objective-c ffmpeg wav flac


    【解决方案1】:

    我能够使用this code 进行解码并使用this code 来实际编写WAV 标头/正文。

    另外,this 在解码 NSData 而不是文件方面非常有帮助。

    这是我完成的解码器,虽然我不希望它在任何情况下都能正常工作,除了我的。

    //
    //  FlacToWavConverter.m
    //  SuperpoweredMQAExample
    //
    //  Created by Tony Lawrence on 5/18/17.
    //  Copyright © 2017 imect. All rights reserved.
    //
    
    #import "FlacToWavConverter.h"
    #import "avformat.h"
    #import "avcodec.h"
    #import "avutil.h"
    #import "swresample.h"
    #import "file.h"
    
    @implementation FlacToWavConverter
    
    +(NSURL*)convertFlacToWav:(NSData*)data {
    
        //const char* input_filename = [filePath UTF8String];
        int buffer_size = 16384;
    
        // This call is necessarily done once in your app to initialize
        // libavformat to register all the muxers, demuxers and protocols.
        av_register_all();
    
        // A media container
        AVFormatContext* container = avformat_alloc_context();
    
        //Make a custom IO context so that we can read from memory instead of a file...
        unsigned char* iobuffer = av_malloc(buffer_size);
        struct buffer_data bd = { 0 };
        bd.ptr = (uint8_t*)data.bytes;
        bd.size = data.length;
        AVIOContext* ioContext = avio_alloc_context(iobuffer, buffer_size, 0, &bd, &read_packet, NULL, NULL);
    
        container->pb = ioContext;
    
        if (avformat_open_input(&container, "arbitrary", NULL, NULL) < 0) {
            NSLog(@"Could not open file");
        }
    
        if (avformat_find_stream_info(container, NULL) < 0) {
            NSLog(@"Could not find file info");
        }
    
        int stream_id = -1;
    
        // To find the first audio stream. This process may not be necessary
        // if you can gurarantee that the container contains only the desired
        // audio stream
        int i;
        for (i = 0; i < container->nb_streams; i++) {
            if (container->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
                stream_id = i;
                break;
            }
        }
    
        if (stream_id == -1) {
            NSLog(@"Could not find an audio stream");
        }
    
        // Extract some metadata
        AVDictionary* metadata = container->metadata;
    
        // Find the apropriate codec and open it
        AVCodecContext* codec_context = container->streams[stream_id]->codec;
    
        AVCodec* codec = avcodec_find_decoder(codec_context->codec_id);
    
        if (avcodec_open2(codec_context, codec, NULL) < 0) {
            NSLog(@"Could not find open the needed codec");
        }
    
        NSMutableData *pcmFile = [NSMutableData new];
    
        AVPacket packet;
        int8_t buffer[buffer_size];
    
        while (1) {
    
            //buffer_size = AVCODEC_MAX_AUDIO_FRAME_SIZE;
    
            // Read one packet into `packet`
            if (av_read_frame(container, &packet) < 0) {
                break;  // End of stream. Done decoding.
            }
    
            // Decodes from `packet` into the buffer
            if (avcodec_decode_audio3(codec_context, (int16_t*)buffer, &buffer_size, &packet) < 1) {
                break;  // Error in decoding
            }
    
            // Send the buffer contents to the audio device
            [pcmFile appendBytes:buffer length:buffer_size];
    
        }
    
        avformat_close_input(&container);
    
        //fprintf(stdout, "Done playing. Exiting...");
    
        NSURL *file = [FlacToWavConverter getAndCreatePlayableFileFromPcmData:pcmFile];
    
        NSLog(@"Got a playable file maybe? %@", [file absoluteString]);
    
        return file;
    }
    
    +(NSURL *) getAndCreatePlayableFileFromPcmData:(NSData *)data
    {
        NSArray *dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *docsDir = [dirPaths objectAtIndex:0];
        NSString *wavFilePath = [docsDir stringByAppendingPathComponent:@"output.wav"];
    
        //NSLog(@"PCM data : %@",data);
    
        FILE *fout;
    
        short NumChannels = 2;
        short BitsPerSample = 16;
        int SamplingRate = 44100;
        int numOfSamples = [data length];
    
        int ByteRate = NumChannels*BitsPerSample*SamplingRate/8;
        short BlockAlign = NumChannels*BitsPerSample/8;
        int DataSize = NumChannels*numOfSamples*BitsPerSample/8;
        int chunkSize = 16;
        int totalSize = 46 + DataSize;
        short audioFormat = 1;
    
        if((fout = fopen([wavFilePath cStringUsingEncoding:1], "w")) == NULL)
        {
            printf("Error opening out file ");
        }
    
        fwrite("RIFF", sizeof(char), 4,fout);
        fwrite(&totalSize, sizeof(int), 1, fout);
        fwrite("WAVE", sizeof(char), 4, fout);
        fwrite("fmt ", sizeof(char), 4, fout);
        fwrite(&chunkSize, sizeof(int),1,fout);
        fwrite(&audioFormat, sizeof(short), 1, fout);
        fwrite(&NumChannels, sizeof(short),1,fout);
        fwrite(&SamplingRate, sizeof(int), 1, fout);
        fwrite(&ByteRate, sizeof(int), 1, fout);
        fwrite(&BlockAlign, sizeof(short), 1, fout);
        fwrite(&BitsPerSample, sizeof(short), 1, fout);
        fwrite("data", sizeof(char), 4, fout);
        fwrite(&DataSize, sizeof(int), 1, fout);
    
        fclose(fout);
    
        NSMutableData *pamdata = [NSMutableData dataWithData:data];
        NSFileHandle *handle;
        handle = [NSFileHandle fileHandleForUpdatingAtPath:wavFilePath];
        [handle seekToEndOfFile];
        [handle writeData:pamdata];
        [handle closeFile];
    
        NSLog(@"Saved wav: %@", wavFilePath);
    
        return [NSURL URLWithString:wavFilePath];
    }
    
    struct buffer_data {
        uint8_t *ptr;
        size_t size; ///< size left in the buffer
    };
    
    
    static int read_packet(void *opaque, uint8_t *buf, int buf_size)
    {
        struct buffer_data *bd = (struct buffer_data *)opaque;
        buf_size = FFMIN(buf_size, bd->size);
        //printf("ptr:%p size:%zu\n", bd->ptr, bd->size);
        /* copy internal buffer data to buf */
        memcpy(buf, bd->ptr, buf_size);
        bd->ptr  += buf_size;
        bd->size -= buf_size;
        return buf_size;
    }
    
    @end
    

    【讨论】:

      猜你喜欢
      • 2014-06-13
      • 2013-07-12
      • 2020-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-06
      • 1970-01-01
      • 2015-02-03
      相关资源
      最近更新 更多