Skip to content

Instantly share code, notes, and snippets.

@justinlevi
Last active November 18, 2020 15:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save justinlevi/7a846070ee6e7e245cc3 to your computer and use it in GitHub Desktop.
Save justinlevi/7a846070ee6e7e245cc3 to your computer and use it in GitHub Desktop.
Swift CAToneFileGenerator "Learning Core Audio" Example
//: Playground - noun: a place where people can play
import UIKit
import Foundation
import AudioToolbox
import AVFoundation
import XCPlayground
func CheckError(error:OSStatus) {
if error == 0 {return}
switch(error) {
// AudioToolbox
case kAUGraphErr_NodeNotFound:
print("Error:kAUGraphErr_NodeNotFound \n");
case kAUGraphErr_OutputNodeErr:
print( "Error:kAUGraphErr_OutputNodeErr \n");
case kAUGraphErr_InvalidConnection:
print("Error:kAUGraphErr_InvalidConnection \n");
case kAUGraphErr_CannotDoInCurrentContext:
print( "Error:kAUGraphErr_CannotDoInCurrentContext \n");
case kAUGraphErr_InvalidAudioUnit:
print( "Error:kAUGraphErr_InvalidAudioUnit \n");
case kAudioToolboxErr_InvalidSequenceType :
print( " kAudioToolboxErr_InvalidSequenceType ");
case kAudioToolboxErr_TrackIndexError :
print( " kAudioToolboxErr_TrackIndexError ");
case kAudioToolboxErr_TrackNotFound :
print( " kAudioToolboxErr_TrackNotFound ");
case kAudioToolboxErr_EndOfTrack :
print( " kAudioToolboxErr_EndOfTrack ");
case kAudioToolboxErr_StartOfTrack :
print( " kAudioToolboxErr_StartOfTrack ");
case kAudioToolboxErr_IllegalTrackDestination :
print( " kAudioToolboxErr_IllegalTrackDestination");
case kAudioToolboxErr_NoSequence :
print( " kAudioToolboxErr_NoSequence ");
case kAudioToolboxErr_InvalidEventType :
print( " kAudioToolboxErr_InvalidEventType");
case kAudioToolboxErr_InvalidPlayerState :
print( " kAudioToolboxErr_InvalidPlayerState");
case kAudioUnitErr_InvalidProperty :
print( " kAudioUnitErr_InvalidProperty");
case kAudioUnitErr_InvalidParameter :
print( " kAudioUnitErr_InvalidParameter");
case kAudioUnitErr_InvalidElement :
print( " kAudioUnitErr_InvalidElement");
case kAudioUnitErr_NoConnection :
print( " kAudioUnitErr_NoConnection");
case kAudioUnitErr_FailedInitialization :
print( " kAudioUnitErr_FailedInitialization");
case kAudioUnitErr_TooManyFramesToProcess :
print( " kAudioUnitErr_TooManyFramesToProcess");
case kAudioUnitErr_InvalidFile :
print( " kAudioUnitErr_InvalidFile");
case kAudioUnitErr_FormatNotSupported :
print( " kAudioUnitErr_FormatNotSupported");
case kAudioUnitErr_Uninitialized :
print( " kAudioUnitErr_Uninitialized");
case kAudioUnitErr_InvalidScope :
print( " kAudioUnitErr_InvalidScope");
case kAudioUnitErr_PropertyNotWritable :
print( " kAudioUnitErr_PropertyNotWritable");
case kAudioUnitErr_InvalidPropertyValue :
print( " kAudioUnitErr_InvalidPropertyValue");
case kAudioUnitErr_PropertyNotInUse :
print( " kAudioUnitErr_PropertyNotInUse");
case kAudioUnitErr_Initialized :
print( " kAudioUnitErr_Initialized");
case kAudioUnitErr_InvalidOfflineRender :
print( " kAudioUnitErr_InvalidOfflineRender");
case kAudioUnitErr_Unauthorized :
print( " kAudioUnitErr_Unauthorized");
default:
print("huh?")
}
}
let SAMPLE_RATE:Float64 = 44100
let DURATION = 0.001
let TONE:Double = 440 // Hz
let FILE_NAME = "\(TONE)-square.aif"
//let path = NSBundle.mainBundle().pathForResource(FILE_NAME, ofType: "aif")!
//let audioURL = NSURL(fileURLWithPath: path)
let fileManager = NSFileManager.defaultManager()
let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
if let documentDirectory: NSURL = urls.first {
let fileURL = documentDirectory.URLByAppendingPathComponent(FILE_NAME)
fileURL
// Prepare the format
var audioFormat = AudioStreamBasicDescription()
audioFormat.mSampleRate = SAMPLE_RATE;
audioFormat.mFormatID = UInt32(kAudioFormatLinearPCM)
audioFormat.mFormatFlags = UInt32(kLinearPCMFormatFlagIsBigEndian) | UInt32(kLinearPCMFormatFlagIsSignedInteger) | UInt32(kLinearPCMFormatFlagIsPacked)
audioFormat.mBitsPerChannel = UInt32(16)
audioFormat.mChannelsPerFrame = 1 // Mono
audioFormat.mBytesPerFrame = UInt32(audioFormat.mChannelsPerFrame * 2)
print(audioFormat.mBytesPerFrame)
audioFormat.mFramesPerPacket = 1
audioFormat.mBytesPerPacket = audioFormat.mFramesPerPacket * audioFormat.mBytesPerFrame
print(audioFormat.mBytesPerPacket)
var audioFile:AudioFileID = nil
var theErr = OSStatus(noErr)
/*!
@function AudioFileCreateWithURL
@abstract creates a new audio file (or initialises an existing file)
@discussion creates a new (or initialises an existing) audio file specified by the URL.
Upon success, an AudioFileID is returned which can be used for subsequent calls
to the AudioFile APIs.
@param inFileRef an CFURLRef fully specifying the path of the file to create/initialise
@param inFileType an AudioFileTypeID indicating the type of audio file to create.
@param inFormat an AudioStreamBasicDescription describing the data format that will be
added to the audio file.
@param inFlags relevant flags for creating/opening the file.
if kAudioFileFlags_EraseFile is set, it will erase an existing file
if not set, then the Create call will fail if the URL is an existing file
@param outAudioFile if successful, an AudioFileID that can be used for subsequent AudioFile calls.
@result returns noErr if successful.
*/
// extern OSStatus
// AudioFileCreateWithURL (CFURLRef inFileRef,
// AudioFileTypeID inFileType,
// const AudioStreamBasicDescription *inFormat,
// UInt32 inFlags,
// AudioFileID *outAudioFile) __OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
theErr = AudioFileCreateWithURL(fileURL, UInt32(kAudioFileAIFFType), &audioFormat, .EraseFile, &audioFile)
let maxSampleCount:CLong = CLong(SAMPLE_RATE * DURATION)
var sampleCount = 0
var bytesToWrite:UInt32 = 2
let wavelengthInSamples = SAMPLE_RATE / TONE
SHRT_MAX
Int16.max
while sampleCount < maxSampleCount {
for i in 0..<Int(wavelengthInSamples){
// Square Wave
//var sample:Int16 = i < Int(wavelengthInSamples) / 2 ? Int16.max : Int16.min //12 & 13
// Saw Wave
var sample = Int16(((Double(i) / wavelengthInSamples) * Double(Int16.max) * 2) - Double(Int16.max))
// Sin Wave
//var sample = Int16(Double(Int16.max) * sin(2 * M_PI * (Double(i) / wavelengthInSamples)))
sample
//theErr = AudioFileWriteBytes(audioFile, 0, Int64(sampleCount * 2), &bytesToWrite, &sample)
sampleCount++
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment