2016-09-29 4 views
1

내 응용 프로그램에서 오디오 파일을 생성해야하며 마지막 Android 버전 다음에 파일 생성기를 쓰고 있습니다. 안드로이드에서는 OKIO을 사용하여 기본 NSData를 사용하는 IO 및 IOS를 처리합니다.WAV 파일을 만들 때 잘못된 바이트가 생성되었습니다.

모든 WAV 파일에는 데이터 판독기 (미디어 플레이어)에 대한 매개 변수를 알리기위한 머리글이 필요합니다.

인터넷에서 제공되는 일부 사양에 따라 바이트를 쓰는이 파일 생성기를 사용합니다.

//Audio file content, this variable will be used 
//to storage the audio data (PCM). 
var content = [UInt8]() //This is not empty. 
var fileSize: Int = 0 //this is not zero. 

//Total size of the file, with the header. 
let totalFileSize = fileSize + HEADER_SIZE 

//Header data 
let header = NSMutableData() 

//RIFF 
header.append([UInt8]("RIFF".utf8), length: 4) 

//Size of the entity file 
header.append(Data(bytes: readInt(Int32(totalFileSize).littleEndian))) 

//WAVE 
header.append([UInt8]("WAVE".utf8), length: 4) 

//FMT 
header.append([UInt8]("fmt ".utf8), length: 4) 

//BITRATE 
header.append(Data(bytes: readInt(BITRATE.littleEndian))) 

//Audio format 
var audioFormat = AUDIO_FORMAT_PCM.littleEndian 
header.append(&audioFormat, length: 2) 

//Number of channels 
var audioChannels = CHANNELS.littleEndian 
header.append(&audioChannels, length: 2) 

//Sample rate 
var sampleRate = SAMPLE_RATE.littleEndian 
header.append(&sampleRate, length: 4) 

//Byte rate 
var byteRate = ((SAMPLE_RATE*UInt32(CHANNELS)*UInt32(BYTES_PER_SAMPLE))/UInt32(8)).littleEndian 
header.append(&byteRate, length: 4) 

//Block align 
var blockAlign = (UInt16(CHANNELS) * UInt16(BYTES_PER_SAMPLE)/UInt16(8)).littleEndian 
header.append(&blockAlign, length: 2) 

//Bytes per sample 
var bytesPerSample = BYTES_PER_SAMPLE.littleEndian 
header.append(&bytesPerSample, length: 2) 

//Data 
header.append([UInt8]("data".utf8), length: 4) 

//Size of the audio data 
var sizeLittleEndian = UInt32(fileSize).littleEndian 
header.append(&sizeLittleEndian, length: 4) 

print(header.length) //44 

이 버퍼에 쓰기 지능이 방법을 사용

안드로이드에서
func readInt(_ i: Int32) -> [UInt8] { 
    return [UInt8(truncatingBitPattern: (i >> 24) & 0xff), 
      UInt8(truncatingBitPattern: (i >> 16) & 0xff), 
      UInt8(truncatingBitPattern: (i >> 8) & 0xff), 
      UInt8(truncatingBitPattern: (i  ) & 0xff)] 
} 

이 파일은 어떤 문제없이 생성되고있다. 하지만 iOS에서는이 두 매개 변수가 잘못되었습니다.

정말 무슨 일이 일어나고 있는지 모르는 3, 당신이 나를

enter image description here

을 도울 수있는 스위프트 (아이폰 OS 코드에 의해 생성 된 안드로이드 코드와 바닥에 생성 된 대부분의 정상 파일)을 봐?

+0

해결 했습니까? – astromme

+0

예 :) 해결되었습니다! –

+0

여기에 답변을 게시 할 수 있습니까? – astromme

답변

0

작성된 totalFileSize은 Android에서 big endian으로 보이지만 Android에서는 작습니다. 어쩌면 당신은 .littleEndian입니다.

아이폰 OS data 블록이 그럴듯 샘플 값이 data 후,하지만 당신은 어쩌면 일부의 CoreAudio 구조 (AN AudioUnit의 주소? ExtAudioFile을 촬영 한 것 같은 iOS에서 그것이? 보이는 안드로이드를 마우스 오른쪽 버튼으로 하나, 보이지 않는

AudioConverter?).

+0

데이터를 제공하는 코드를 제거했습니다. 그러나 단순히 PCM 파일을 읽고, 임시 버퍼에서 바이트 및이 바이트를 가져옵니다. –

+0

첫 번째 질문에 대해, 나는 정말로 모르겠다. 이것은 가치 또는 위치와 관련이 있는가? –

+0

아아, wav 파일에'.caf' 파일의 헤더를 작성했습니다. 그것은 끝내지 않을 것입니다. 예,'.caf' 파일은 lpcm이지만 어떤 형식입니까? 먼저 해독해야 할 것입니다. 'totalFileSize'의 값이 wav 파일에서 잘못되었습니다. –

0

주요 문제 중 하나는 readInt 함수가 빅 엔디안을 반환한다는 것이고 리틀 엔디안이어야한다는 것입니다.

어쨌든,이 나를 위해 일했다. 이것이 내가 WAV 파일을 초기화하는 방법입니다. 누군가가 도움이되기를 바랍니다.

func createHeader() { 

    let sampleRate:Int32 = 44100 
    let chunkSize:Int32 = 36 
    let subChunkSize:Int32 = 16 
    let format:Int16 = 1 
    let channels:Int16 = 1 
    let bitsPerSample:Int16 = 16 
    let byteRate:Int32 = sampleRate * Int32(channels * bitsPerSample/8) 
    let blockAlign: Int16 = channels * 2 
    let dataSize:Int32 = 0 

    let header = NSMutableData() 

    header.append([UInt8]("RIFF".utf8), length: 4) 
    header.append(intToByteArray(chunkSize), length: 4) 

    //WAVE 
    header.append([UInt8]("WAVE".utf8), length: 4) 

    //FMT 
    header.append([UInt8]("fmt ".utf8), length: 4) 

    header.append(intToByteArray(subChunkSize), length: 4) 
    header.append(shortToByteArray(format), length: 2) 
    header.append(shortToByteArray(channels), length: 2) 
    header.append(intToByteArray(sampleRate), length: 4) 
    header.append(intToByteArray(byteRate), length: 4) 
    header.append(shortToByteArray(blockAlign), length: 2) 
    header.append(shortToByteArray(bitsPerSample), length: 2) 


    header.append([UInt8]("data".utf8), length: 4) 

    header.append(intToByteArray(dataSize), length: 4) 

    header.write(to: fileURL!, atomically: true) 

} 

func intToByteArray(_ i: Int32) -> [UInt8] { 
    return [ 
      //little endian 
      UInt8(truncatingBitPattern: (i  ) & 0xff), 
      UInt8(truncatingBitPattern: (i >> 8) & 0xff), 
      UInt8(truncatingBitPattern: (i >> 16) & 0xff), 
      UInt8(truncatingBitPattern: (i >> 24) & 0xff) 
    ] 
} 

func shortToByteArray(_ i: Int16) -> [UInt8] { 
    return [ 
     //little endian 
     UInt8(truncatingBitPattern: (i  ) & 0xff), 
     UInt8(truncatingBitPattern: (i >> 8) & 0xff) 
    ] 
}