Converting .M4A File to .Aiff Using Audioconverter Swift

Converting .m4a file to .aiff using AudioConverter Swift


Skip the AudioConverterGetProperty

You actually are not using it.

The following snippet will convert an audio file to AIFF: it reads the sourceFile in one of the supported formats, creates an AIFF encoder, and loops through it using a bufferByteSize buffer. Errors are mildly handled.

Complete code, swift 3:

func convertAudio(_ url: URL, outputURL: URL) {
var error : OSStatus = noErr
var destinationFile : ExtAudioFileRef? = nil
var sourceFile : ExtAudioFileRef? = nil

var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()
var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()

ExtAudioFileOpenURL(url as CFURL, &sourceFile)

var thePropertySize: UInt32 = UInt32(MemoryLayout.stride(ofValue: srcFormat))

ExtAudioFileGetProperty(sourceFile!,
kExtAudioFileProperty_FileDataFormat,
&thePropertySize, &srcFormat)

dstFormat.mSampleRate = 44100 //Set sample rate
dstFormat.mFormatID = kAudioFormatLinearPCM
dstFormat.mChannelsPerFrame = 1
dstFormat.mBitsPerChannel = 16
dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame
dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame
dstFormat.mFramesPerPacket = 1
dstFormat.mFormatFlags = kAudioFormatFlagIsBigEndian |
kAudioFormatFlagIsSignedInteger

// Create destination file
error = ExtAudioFileCreateWithURL(
outputURL as CFURL,
kAudioFileAIFFType,
&dstFormat,
nil,
AudioFileFlags.eraseFile.rawValue,
&destinationFile)
reportError(error: error)

error = ExtAudioFileSetProperty(sourceFile!,
kExtAudioFileProperty_ClientDataFormat,
thePropertySize,
&dstFormat)
reportError(error: error)

error = ExtAudioFileSetProperty(destinationFile!,
kExtAudioFileProperty_ClientDataFormat,
thePropertySize,
&dstFormat)
reportError(error: error)

let bufferByteSize : UInt32 = 32768
var srcBuffer = [UInt8](repeating: 0, count: 32768)
var sourceFrameOffset : ULONG = 0

while(true){
var fillBufList = AudioBufferList(
mNumberBuffers: 1,
mBuffers: AudioBuffer(
mNumberChannels: 2,
mDataByteSize: UInt32(srcBuffer.count),
mData: &srcBuffer
)
)
var numFrames : UInt32 = 0

if(dstFormat.mBytesPerFrame > 0){
numFrames = bufferByteSize / dstFormat.mBytesPerFrame
}

error = ExtAudioFileRead(sourceFile!, &numFrames, &fillBufList)
reportError(error: error)

if(numFrames == 0){
error = noErr;
break;
}

sourceFrameOffset += numFrames
error = ExtAudioFileWrite(destinationFile!, numFrames, &fillBufList)
reportError(error: error)
}

error = ExtAudioFileDispose(destinationFile!)
reportError(error: error)
error = ExtAudioFileDispose(sourceFile!)
reportError(error: error)
}

Supporting method:

func reportError(error: OSStatus) {
// Handle error
}

Invocation:

let sourceUrl = URL(string: Bundle.main.path(forResource: "sample", ofType: "mp3")!)
let paths = NSSearchPathForDirectoriesInDomains(.documentDirectory,
.userDomainMask,
true)
let documentsDirectory = URL(string: paths.first!)
let destUrl = documentsDirectory?.appendingPathComponent("converted.aiff")
if let sourceUrl = sourceUrl, let destUrl = destUrl {
print("from \(sourceUrl.absoluteString) to \(destUrl.absoluteString)")
convertAudio(sourceUrl, outputURL: destUrl)
}

iOS Code to Convert m4a to WAV

If anyone else needs some code to do this here it is in Swift

func convertAudioFile(sourceURL: CFURLRef, destinationURL: 
CFURLRef, outputFormat: OSType ,
outputSampleRate: Float64) -> OSStatus
{
var error : OSStatus = noErr
var destinationFile : ExtAudioFileRef = nil
var sourceFile : ExtAudioFileRef = nil

var srcFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()
var dstFormat : AudioStreamBasicDescription = AudioStreamBasicDescription()

var audioConverter : AudioConverterRef = nil

audioConverter = AudioConverterRef.init()

ExtAudioFileOpenURL(sourceURL, &sourceFile)

var thePropertySize: UInt32 = UInt32(strideofValue(srcFormat))

ExtAudioFileGetProperty(sourceFile, kExtAudioFileProperty_FileDataFormat, &thePropertySize, &srcFormat)

dstFormat.mSampleRate = (outputSampleRate == 0 ? srcFormat.mSampleRate : outputSampleRate) //Set sample rate

dstFormat.mFormatID = outputFormat
dstFormat.mChannelsPerFrame = 1
dstFormat.mBitsPerChannel = 16
dstFormat.mBytesPerPacket = 2 * dstFormat.mChannelsPerFrame
dstFormat.mBytesPerFrame = 2 * dstFormat.mChannelsPerFrame
dstFormat.mFramesPerPacket = 1
dstFormat.mFormatFlags = kLinearPCMFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger // little-endian

//Create destination file
ExtAudioFileCreateWithURL(destinationURL, kAudioFileCAFType, &dstFormat, nil,
AudioFileFlags.EraseFile.rawValue, &destinationFile)

ExtAudioFileSetProperty(sourceFile, kExtAudioFileProperty_ClientDataFormat, thePropertySize, &dstFormat)
ExtAudioFileSetProperty(destinationFile, kExtAudioFileProperty_ClientDataFormat, thePropertySize, &dstFormat)

var size : UInt32 = UInt32(strideofValue(audioConverter))

ExtAudioFileGetProperty(destinationFile, kExtAudioFileProperty_AudioConverter, &size, &audioConverter)

var canResume : UInt32 = 0

size = UInt32(strideofValue(canResume))

error = AudioConverterGetProperty(audioConverter, kAudioConverterPropertyCanResumeFromInterruption, &size, &canResume)

let bufferByteSize : UInt32 = 32768
var srcBuffer = [UInt8](count: 32768, repeatedValue: 0)

var sourceFrameOffset : ULONG = 0

print("Converting audio file")

while(true){

var fillBufList = AudioBufferList(
mNumberBuffers: 1,
mBuffers: AudioBuffer(
mNumberChannels: 2,
mDataByteSize: UInt32(srcBuffer.count),
mData: &srcBuffer
)
)

var numFrames : UInt32 = 0

if(dstFormat.mBytesPerFrame > 0){
numFrames = bufferByteSize / dstFormat.mBytesPerFrame
}

ExtAudioFileRead(sourceFile, &numFrames, &fillBufList)

if(numFrames == 0){
error = noErr;
break;
}

sourceFrameOffset += numFrames

error = ExtAudioFileWrite(destinationFile, numFrames, &fillBufList)
}

ExtAudioFileDispose(destinationFile)
ExtAudioFileDispose(sourceFile)

let audioAsset = AVURLAsset.init(URL: destinationURL, options: nil)
if(audioAsset.duration.seconds < 5.0){
error = -2500
}

return error;

kAudioFormat for .aif audio file conversion?

I haven' worked with AVAssetWriter so far, but I assume its basically a format description as in Core Audio with ASBDs.

An example of a AudioBasicStreamDescription defined for AIFF see for example here:

aiffFormat.mSampleRate = sampleRate;
aiffFormat.mFormatID = kAudioFormatLinearPCM;
aiffFormat.mBytesPerPacket = 2;
aiffFormat.mFramesPerPacket = 1;
aiffFormat.mBytesPerFrame = 2;
aiffFormat.mChannelsPerFrame = 2; // for STEREO
aiffFormat.mBitsPerChannel = 16;
aiffFormat.mFormatFlags = (kLinearPCMFormatFlagIsBigEndian | kAudioFormatFlagIsPacked | kLinearPCMFormatFlagIsSignedInteger) ;
aiffFormat.mBitsPerChannel = sizeof(float) * 8;
aiffFormat.mBytesPerFrame = aiffFormat.mChannelsPerFrame * sizeof(Float32);
aiffFormat.mBytesPerPacket = aiffFormat.mFramesPerPacket * aiffFormat.mBytesPerFrame;

In your above code big endianess has to be set to YES. As mentioned I have never worked with AVAssetWriter, so I am not sure which further parameters have to be set or which not, but with the example stream description above, it should be not too hard to get running.

Reverse an audio file Swift/Objective-C

Yes, there is a way you can process, then export, any of the audio files for which there is iOS support.

However, most of these formats (mp3 to name one) are lossy and compressed. You must first decompress the data, apply the transformation, and recompress. Most transformation you will apply to the audio information should likely be done at the raw, PCM level.

Combining these two statements, you do this in a few passes:

  1. convert original file to a kAudioFormatLinearPCM compliant audio file, like AIFF
  2. process that temporary file (reverse its content)
  3. convert the temporary file back to the original format

Just like if you were applying a transformation to, say, a compressed jpeg image, there will be degradation in the process. The final audio will have, at best, suffered one more compression cycle.

So the true mathematical answer to this approach is actually no.


Just for reference, here is some starter code in swift 3. It needs further refinement to skip the file headers.

var outAudioFile:AudioFileID?
var pcm = AudioStreamBasicDescription(mSampleRate: 44100.0,
mFormatID: kAudioFormatLinearPCM,
mFormatFlags: kAudioFormatFlagIsBigEndian | kAudioFormatFlagIsSignedInteger,
mBytesPerPacket: 2,
mFramesPerPacket: 1,
mBytesPerFrame: 2,
mChannelsPerFrame: 1,
mBitsPerChannel: 16,
mReserved: 0)

var theErr = AudioFileCreateWithURL(destUrl as CFURL!,
kAudioFileAIFFType,
&pcm,
.eraseFile,
&outAudioFile)
if noErr == theErr, let outAudioFile = outAudioFile {
var inAudioFile:AudioFileID?
theErr = AudioFileOpenURL(sourceUrl as! CFURL, .readPermission, 0, &inAudioFile)

if noErr == theErr, let inAudioFile = inAudioFile {

var fileDataSize:UInt64 = 0
var thePropertySize:UInt32 = UInt32(MemoryLayout<UInt64>.stride)
theErr = AudioFileGetProperty(inAudioFile,
kAudioFilePropertyAudioDataByteCount,
&thePropertySize,
&fileDataSize)

if( noErr == theErr) {
let dataSize:Int64 = Int64(fileDataSize)
let theData = UnsafeMutableRawPointer.allocate(bytes: Int(dataSize),
alignedTo: MemoryLayout<UInt8>.alignment)

var readPoint:Int64 = Int64(dataSize)
var writePoint:Int64 = 0

while( readPoint > 0 )
{
var bytesToRead = UInt32(2)

AudioFileReadBytes( inAudioFile, false, readPoint, &bytesToRead, theData)
AudioFileWriteBytes( outAudioFile, false, writePoint, &bytesToRead, theData)

writePoint += 2
readPoint -= 2
}

theData.deallocate(bytes: Int(dataSize), alignedTo: MemoryLayout<UInt8>.alignment)

AudioFileClose(inAudioFile);
AudioFileClose(outAudioFile);
}
}
}

Trying to read AIFF Files Unexpected Error to do with pointer location etc

Your code doesn't appear to check to see if fopen() returns NULL... so if fopen() fails for whatever reason (most likely because the specified file doesn't exist or can't be opened for reading), then your program will crash when fread() tries to dereference the NULL pointer.

Side note: since .AIFF files are binary files, not ASCII, you should be passing "rb" as the second argument to fopen() rather than "r".



Related Topics



Leave a reply



Submit