0

Android アプリを iPhone に移植しています (Android バージョンに基づいて iPhone アプリを改善するようなものです)。大きな非圧縮オーディオ ファイルを分割して結合する必要があります。

現在、すべてのファイルをメモリにロードして分割し、別々の関数に結合しています。100MB以上のファイルでクラッシュします。

これを行うために必要な新しいプロセスは次のとおりです。

2 つの録音 (file1 と file2) と、file2 を file1 内に挿入する分割位置があります。

-file1 と file2 の入力ストリームと、outputfile の出力ストリームを作成します。

- 新しい CAF ヘッダーを書き換えます

-分割ポイントに到達するまでinputStream1からデータを読み取り、そのすべてのデータを出力ファイルに書き込みます。それを出力ストリームに書き込みます。

-inputStream2 からすべてのデータを読み取り、出力ファイルに書き込みます。

-inputStream1 から残りのデータを読み取り、出力ファイルに書き込みます。

プロセスの Android コードは次のとおりです。

    File file1File = new File(file1);
    File file2File = new File(file2);

    long file1Length = file1File.length();
    long file2Length = file2File.length();

    FileInputStream file1ByteStream = new FileInputStream(file1);
    FileInputStream file2ByteStream = new FileInputStream(file2);
    FileOutputStream outputFileByteStream = new FileOutputStream(outputFile);


    // time = fileLength / (Sample Rate * Channels * Bits per sample / 8)
    // convert position to number of bytes for this function
    long sampleRate = eRecorder.RECORDER_SAMPLERATE;
    int channels = 1;
    long bitsPerSample = eRecorder.RECORDER_BPP;
    long bytePositionLength = (position * (sampleRate * channels * bitsPerSample / 8)) / 1000;



    //calculate total data size
            int dataSize = 0;
            dataSize = (int)(file1Length + file2Length);

            WriteWaveFileHeaderForMerge(outputFileByteStream, dataSize,
                    dataSize + 36,
                    eRecorder.RECORDER_SAMPLERATE, 1,
                    2 * eRecorder.RECORDER_SAMPLERATE);




    long bytesWritten = 0;

    int length = 0;

    //set limit for bytes read, and write file1 bytes to outputfile until split position reached
    int limit = (int)bytePositionLength;


    //read bytes to limit
    writeBytesToLimit(file1ByteStream, outputFileByteStream, limit);    
    file1ByteStream.close();


    file2ByteStream.skip(44);//skip wav file header
    writeBytesToLimit(file2ByteStream, outputFileByteStream, (int)file2Length);
    file2ByteStream.close();

    //calculate length of remaining file1 bytes to be written
    long file1offset = bytePositionLength;

    //reinitialize file1 input stream
    file1ByteStream = new FileInputStream(file1);

    file1ByteStream.skip(file1offset);
    writeBytesToLimit(file1ByteStream, outputFileByteStream, (int)file1Length);

    file1ByteStream.close();
    outputFileByteStream.close();

そして、これは私の writeBytesToLimit 関数です:

private void writeBytesToLimit(FileInputStream inputStream, FileOutputStream outputStream, int byteLimit) throws IOException
{
    int bytesRead = 0;
    int chunkSize = 65536;
    int length = 0;
    byte[] buffer = new byte[chunkSize];
    while((length = inputStream.read(buffer)) != -1)
    {
        bytesRead += length;
        if(bytesRead >= byteLimit)
        {
            int leftoverBytes = byteLimit % chunkSize;              
            byte[] smallBuffer = new byte[leftoverBytes];
            System.arraycopy(buffer, 0, smallBuffer, 0, leftoverBytes);
            outputStream.write(smallBuffer);
            break;
        }

        if(length == chunkSize)
            outputStream.write(buffer);
        else
        {
            byte[] smallBuffer = new byte[length];
            System.arraycopy(buffer, 0, smallBuffer, 0, length);
            outputStream.write(smallBuffer);
        }

    }

}

iOSでこれを行うにはどうすればよいですか? 2 つの NSInputStream と 1 つの NSOutputStream に同じデリゲートを使用すると、非常に面倒になるようです。これを行う(そしてきれいにする)方法の例を見た人はいますか?

4

1 に答える 1

2

私は NSFileHandle を使用することになりました。たとえば、これは私がやっていることの最初の部分です。

NSData *readData = [[NSData alloc] init];
NSFileHandle *reader1 = [NSFileHandle fileHandleForReadingAtPath:file1Path];
NSFileHandle *writer = [NSFileHandle fileHandleForWritingAtPath:outputFilePath];

//start reading data from file1 to split point and writing it to file
long bytesRead = 0;
while(bytesRead < splitPointInBytes)
{

    //read a chunk of data
    readData = [reader1 readDataOfLength:chunkSize];
    if(readData.length == 0)break;
    //trim data if too much was read
    if(bytesRead + readData.length > splitPointInBytes)
    {
        //get difference of read bytes and byte limit
        long difference = bytesRead + readData.length - splitPointInBytes;

        //trim data
        NSMutableData *readDataMutable = [NSMutableData dataWithData:readData];
        [readDataMutable setLength:readDataMutable.length - difference];
        readData = [NSData dataWithData:readDataMutable];

        NSLog(@"Too much data read, trimming");
    }

    //write data to output file
    [writer writeData:readData];

    //update byte counter
    bytesRead += readData.length;
}
long file1BytesWritten = bytesRead;
于 2012-12-20T22:34:20.197 に答える