Last active
July 23, 2018 13:25
-
-
Save rolfbjarne/dc947383a6c9172bc664 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Foundation; | |
using System; | |
using System.CodeDom.Compiler; | |
using UIKit; | |
using AudioToolbox; | |
using System.Runtime.InteropServices; | |
using AVFoundation; | |
using System.Linq; | |
namespace TestAvAudioEngineApp | |
{ | |
partial class TestAvAudioEngineAppViewController : UIViewController | |
{ | |
public static uint kOutputBus = 0; | |
public static uint kInputBus = 1; | |
AVAudioEngine audioEngine; | |
AVAudioInputNode audioInputNode; | |
AVAudioMixerNode mixerNode; | |
public TestAvAudioEngineAppViewController (IntPtr handle) : base (handle) | |
{ | |
} | |
public override void ViewDidLoad () | |
{ | |
base.ViewDidLoad (); | |
//create main block...implictely creates an output | |
audioEngine = new AVAudioEngine (); | |
var playerNode = new AVAudioPlayerNode (); | |
//get microphone input from engine node | |
audioInputNode = audioEngine.InputNode; | |
//get mixer node from engine | |
mixerNode = audioEngine.MainMixerNode; | |
//connect the chain | |
var inputFormat = audioInputNode.GetBusInputFormat (0); | |
var inChannels = inputFormat.ChannelCount; | |
var outputFormat = playerNode.GetBusOutputFormat (0); | |
var outChannels = outputFormat.ChannelCount; | |
var sampleRate = inputFormat.SampleRate; | |
Console.WriteLine ("Input format: {0}", inputFormat); | |
Console.WriteLine ("Output format: {0}", outputFormat); | |
var channels = inChannels; | |
int counter = 0; | |
audioInputNode.InstallTapOnBus (0, 4096, inputFormat, delegate(AVAudioPcmBuffer inBuffer, AVAudioTime when) { | |
var outBuffer = new AVAudioPcmBuffer (inputFormat, inBuffer.FrameCapacity); | |
outBuffer.FrameLength = inBuffer.FrameLength; | |
var sr = inputFormat.SampleRate; | |
unsafe { | |
var outDataPointers = new float*[channels]; | |
var inDataPointers = new float*[channels]; | |
for (int i = 0; i < channels; i++) { | |
// buffer.FloatChannelData is a native array of pointers to audio data. | |
// convert that into a managed array of pointers to audio data. | |
outDataPointers [i] = (float *) Marshal.ReadIntPtr (outBuffer.FloatChannelData, i * IntPtr.Size); | |
inDataPointers [i] = (float *) Marshal.ReadIntPtr (inBuffer.FloatChannelData, i * IntPtr.Size); | |
} | |
for (int i = 0; i < channels; i++) { | |
// get the pointer to the audio data for the channel we're processing. | |
var outptr = outDataPointers [i]; | |
var inptr = inDataPointers [i]; | |
for (int j = 0; j < outBuffer.FrameLength; j++) { | |
var val = (float) Math.Sin(441.0*j*2*Math.PI/sampleRate) / 10f; | |
// mix sine wave with mic input. | |
*outptr++ = val + *inptr++; | |
} | |
} | |
} | |
// schedule the audio data we've created | |
playerNode.ScheduleBuffer (outBuffer, () => { | |
}); | |
}); | |
audioEngine.AttachNode (playerNode); | |
audioEngine.Connect (playerNode, mixerNode, inputFormat); | |
NSError error; | |
audioEngine.StartAndReturnError (out error); | |
playerNode.Play (); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I'm surprised you can allocate:
within the block. Seems like you should allocate that outside the block...