//
//  Singer.m
//  musiculesdev
//
//  Created by Dylan on 2/20/09.
//  Copyright 2009 __MyCompanyName__. All rights reserved.
//

#import <AudioUnit/AudioUnit.h>
#import <math.h>

#import "Singer.h"


#define kOutputBus 0

#define kSampleRate 44100
//44100.0f
#define kWaveform (M_PI * 2.0f / kSampleRate)
fr1=500;

@implementation Singer
@synthesize fr1, fr2, fr3, fr4, LB1;

OSStatus playbackCallback(void *inRefCon,
						  AudioUnitRenderActionFlags *ioActionFlags,
						  const AudioTimeStamp *inTimeStamp,
						  UInt32 inBusNumber, 
						  UInt32 inNumberFrames,
						  AudioBufferList *ioData) {	
	
	//Singer *me = (Singer *)inRefCon;
	
	static int phase = 0;
	
	for(UInt32 i = 0; i < ioData->mNumberBuffers; i++) {
		
		int samples = ioData->mBuffers[i].mDataByteSize / sizeof(SInt16);
		
		SInt16 values[samples];
		
		float waves;
		float volume=.5;
		
		for(int j = 0; j < samples; j++) {
			
			
			waves = 0;
			
			
			waves += sin(kWaveform * fr1 * phase)*volume;
			waves += sin(kWaveform * fr1 * phase)*volume;
			waves += sin(kWaveform * fr1 * phase)*volume;
			waves += sin(kWaveform * 100 * phase)*volume;			 
			
			waves *= 32500 / 4; // <--------- make sure to divide by how many waves you're stacking
			
			values[j] = (SInt16)waves;
			values[j] += values[j]<<16;
			
			phase++;
			
		}
		
		memcpy(ioData->mBuffers[i].mData, values, samples * sizeof(SInt16));
	
	}
	
	
	return noErr;
	
}


-(id)init {
	
	if(self = [super init]) {
						
		[self initAudio];
		
	}
	
	return self;
	
}

-(void)initAudio {
	
	OSStatus status;
	
	AudioComponentDescription desc;
	desc.componentType = kAudioUnitType_Output;
	desc.componentSubType = kAudioUnitSubType_RemoteIO;
	desc.componentFlags = 0;
	desc.componentFlagsMask = 0;
	desc.componentManufacturer = kAudioUnitManufacturer_Apple;
	
	AudioComponent outputComponent = AudioComponentFindNext(NULL, &desc);
	
	status = AudioComponentInstanceNew(outputComponent, &audioUnit);
	
	UInt32 flag = 1;
	status = AudioUnitSetProperty(audioUnit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));
	
	AudioStreamBasicDescription audioFormat;
	audioFormat.mSampleRate = kSampleRate;
	audioFormat.mFormatID = kAudioFormatLinearPCM;
	audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsPacked;
	audioFormat.mFramesPerPacket = 1;
	audioFormat.mChannelsPerFrame = 1;
	audioFormat.mBitsPerChannel = 16;
	audioFormat.mBytesPerPacket = 2;
	audioFormat.mBytesPerFrame = 2;
	
	status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, kOutputBus, &audioFormat, sizeof(audioFormat));
	
	AURenderCallbackStruct callbackStruct;
	callbackStruct.inputProc = playbackCallback;
	callbackStruct.inputProcRefCon = self;
	
	status = AudioUnitSetProperty(audioUnit, kAudioUnitProperty_SetRenderCallback, kAudioUnitScope_Global, kOutputBus, &callbackStruct, sizeof(callbackStruct));
	
	status = AudioUnitInitialize(audioUnit);
	
}

-(void)start {
	
	OSStatus status;
	
	status = AudioOutputUnitStart(audioUnit);
	
}

-(void)stop {
	
	OSStatus status;
	
	status = AudioOutputUnitStop(audioUnit);
	
}

-(void)dealloc {
	
	AudioUnitUninitialize(audioUnit);
	
	[super dealloc];
	
}

@end
