Skip to content

Instantly share code, notes, and snippets.

@rolfbjarne
Last active July 23, 2018 13:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rolfbjarne/dc947383a6c9172bc664 to your computer and use it in GitHub Desktop.
Save rolfbjarne/dc947383a6c9172bc664 to your computer and use it in GitHub Desktop.
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 ();
}
}
}
@mahboud
Copy link

mahboud commented Apr 16, 2015

I'm surprised you can allocate:

var outBuffer = new AVAudioPcmBuffer (inputFormat, inBuffer.FrameCapacity);

within the block. Seems like you should allocate that outside the block...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment