Sign in to follow this  

event that triggers buffer writes in ASIO

This topic is 1602 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I didnt know where to put this cause under "creative" /sound, i dont think i would get any programmers, just musicians.

 

So its here.

 

Anyway, ive got code for initializing asio in c++, its just that I think its some event call that autotriggers every time ASIO needs buffers to be written/read every so time segment, but im not sure how it actually looks in c++, the demo I have is c# and im not quite sure how to convert it to c.

 

heres a sample of the demo I have, what it looks like->  (its not big)

 

Just I guess how do I convert it to c++?

 

The actual buffer update is at the bottom, and asio automatically calls this I presume,  a million thanks for any help!

 

Its an event handler "driver.BufferUpdate += new EventHandler(AsioDriver_BufferUpdate);"   thats the key part I just need to know how to handle an event

in c++ I guess, so some non audio guy could help me for sure.    so the questions about "how do event handlers work in c++"

 
using System;
using System.Threading;
using BlueWave.Interop.Asio;
 
namespace BlueWave.Interop.Asio.Test
{
/// <summary>
/// A simple test console application
/// </summary>
public class TestConsole
{
        // we'll store the samples in a 2d array (one dimension is the buffer index,
        // the other is the delay count)
private static float[,] _delayBuffer;
 
// how many buffers to keep for delay purposes
private const int MaxBuffers = 100;
 
// the delay (in whole buffers) for the left and right channels
        private static int _leftDelay = 0;
        private static int _rightDelay = 0;
 
        // a counter to keep track of where we are in the delay array
        private static int _counter;
        
        // STAThread is ESSENTIAL to make this work
[STAThread] public static void Main(string[] args)
{
            // no messing, this is high priority stuff
Thread.CurrentThread.Priority = ThreadPriority.Highest;
            
// make sure we have at least one ASIO driver installed
if (AsioDriver.InstalledDrivers.Length == 0)
{
Console.WriteLine("There appears to be no ASIO drivers installed on your system.");
Console.WriteLine("If your soundcard supports ASIO natively, install the driver");
Console.WriteLine("from the support disc. If your soundcard has no native ASIO support");
Console.WriteLine("you can probably use the generic ASIO4ALL driver.");
Console.WriteLine("You can download this from: http://www.asio4all.com/");
Console.WriteLine("It's very good!");
Console.WriteLine();
Console.WriteLine("Hit Enter to exit...");
Console.ReadLine();
return;
}
 
            // bingo, we've go at least one
Console.WriteLine("Your system has the following ASIO drivers installed:");
Console.WriteLine();
 
            // so iterate through them
for (int index = 0; index < AsioDriver.InstalledDrivers.Length; index++)
{
                // and display them
Console.WriteLine(string.Format("  {0}. {1}", index + 1, AsioDriver.InstalledDrivers[index]));
}
 
Console.WriteLine();
 
int driverNumber = 0;
 
            // get them to choose one
while (driverNumber < 1 || driverNumber > AsioDriver.InstalledDrivers.Length)
{
// we'll keep telling them this until they make a valid selection
Console.Write("Select which driver you wish to use (x for exit): ");
ConsoleKeyInfo key = Console.ReadKey();
Console.WriteLine();
 
// deal with exit condition
if (key.KeyChar == 'x') return;
 
// convert from ASCII to int
driverNumber = key.KeyChar - 48;
}
 
Console.WriteLine();
Console.WriteLine("Using: " + AsioDriver.InstalledDrivers[driverNumber - 1]);
Console.WriteLine();
 
// load and activate the desited driver
AsioDriver driver = AsioDriver.SelectDriver(AsioDriver.InstalledDrivers[driverNumber - 1]);
 
// popup the driver's control panel for configuration
            driver.ShowControlPanel();
 
// now dump some details
            Console.WriteLine("  Driver name = " + driver.DriverName);
            Console.WriteLine("  Driver version = " + driver.Version);
            Console.WriteLine("  Input channels = " + driver.NumberInputChannels);
            Console.WriteLine("  Output channels = " + driver.NumberOutputChannels);
            Console.WriteLine("  Min buffer size = " + driver.BufferSizex.MinSize);
            Console.WriteLine("  Max buffer size = " + driver.BufferSizex.MaxSize);
            Console.WriteLine("  Preferred buffer size = " + driver.BufferSizex.PreferredSize);
            Console.WriteLine("  Granularity = " + driver.BufferSizex.Granularity);
            Console.WriteLine("  Sample rate = " + driver.SampleRate);
 
// get our driver wrapper to create its buffers
driver.CreateBuffers(false);
 
// write out the input channels
            Console.WriteLine("  Input channels found = " + driver.InputChannels.Length);
Console.WriteLine("  ----");
 
            foreach (Channel channel in driver.InputChannels)
{
Console.WriteLine(channel.Name);
}
 
// and the output channels
            Console.WriteLine("  Output channels found = " + driver.OutputChannels.Length);
            Console.WriteLine("----");
 
            foreach (Channel channel in driver.OutputChannels)
{
Console.WriteLine(channel.Name);
}
 
            // create a an array of standard sized buffers with a size of 100 
            _delayBuffer = new float[driver.BufferSizex.PreferredSize, MaxBuffers];
            
            // this is our buffer fill event we need to respond to
            driver.BufferUpdate += new EventHandler(AsioDriver_BufferUpdate);
 
            // and off we go
            driver.Start();
 
            // wait for enter key
            Console.WriteLine();
            Console.WriteLine("Press Enter to end");
Console.ReadLine();
 
            // and all donw
            driver.Stop();
}
 
        /// <summary>
/// Called when a buffer update is required
/// </summary>
private static void AsioDriver_BufferUpdate(object sender, EventArgs e)
{
// the driver is the sender
            AsioDriver driver = sender as AsioDriver;
 
// get the input channel and the stereo output channels
            Channel input = driver.InputChannels[0];
Channel leftOutput = driver.OutputChannels[0];
Channel rightOutput = driver.OutputChannels[1];
            Channel left2Output = driver.OutputChannels[2];
            Channel right2Output = driver.OutputChannels[3];
 
            short saw = 0;
             
for (int index = 0; index < leftOutput.BufferSize; index++)
{
                leftOutput[index] = saw;// input[index];
                rightOutput[index] = saw;// input[index];
                left2Output[index] = saw;// input[index];
                right2Output[index] = saw;// input[index];
                saw++;
            }
}
}
}
 
 
 
Edited by rouncer

Share this post


Link to post
Share on other sites

In C, the handler is nothing more than a pointer to a function that is called every time the buffers need to be handled. In general, the complete initialization code using the raw ASIO interface looks something like this.

double SampleRate = 48000;
long BufferSize = 480;
 
std::vector<ASIOBufferInfo> BufferInfo; // fill this with the desired input and output channels
 
ASIO->init(nullptr);
ASIO->setSampleRate(SampleRate);
ASIO->createBuffers(BufferInfo.data(), BufferInfo.size(), BufferSize, &callbacks);
 
ASIO->start();

The callbacks structure has to be persistent throughout the duration of the processing. Keeping it as a global is just fine for that purpose. The callback function will be called for every BufferSize samples, and you can read the samples from, or write the samples to, the buffers contained in the BufferInfo vector.

ASIOCallbacks callbacks = {
    callback,
    ...,
    ...,
    ...
};
 
void callback(long index, long) {
    // process BufferInfo[n].buffer[index] here for n=0 to n=BufferInfo.size()-1.
    // check BufferInfo[n].isInput to determine whether buffer n is an input or output, and
    // check BufferInfo[n].channelNum to determine which (input or output) channel it is.
}

And when done, you stop and clean up the driver resources.

ASIO->strop();
ASIO->disposeBuffers();

This is just the order and structure of the calls you have to make. You have to be aware of all parameters, create the buffers, obtain channel infomrations to determine the exact datatype of the audio buffers, and understand the four (!) callbacks in the callback structure.

 

The official SDK contains the relevant documentation and sample code.

Share this post


Link to post
Share on other sites

This topic is 1602 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this