Audio Classes Library w/ n-Channel Real-Time Mixer demo


<You can right-click on the channel for a context menu that includes displaying the spectrum graph.>

Environment: Win 98/NT/2000, Visual C++ 6

The AudioClasses Library demonstrates the following:

  • Loading a wave file manually. (thanks to Timothy J. Weber's Rifffile code)
  • The Audio Compression Manager API
  • Mixing n-channels of stereo audio
  • Waveform Audio API : Outputing audio data to sound device
  • Implimenting a Spectrum Analyzer and Spectrum Analyzer (peak-valley) Graph
  • Fast Fourier Transforms
  • Mixer Control : Implimenting a custom listbox

The AudioClasses library simplifies much of the work involved in playing from a compressed sound source and includes mixing of many sources at once in real-time into a single sound stream. The library is based on audio streams. You can connect stream objects together like a chain to perform the desired operation.

There are two base types of streams, PlayStream and FilterStream. A PlayStream is meant to be a source of audio data, usually from a file but can be from another source such as a database. A PlayStream class impliments the 'WaveBuffer GetBuffer()' virtual method providing a chunk of audio data (a WaveBuffer) to the requesting object. The requesting object can be another input stream, the player, or a custom object. The WaveStream (loads a wave file) is an implimentation of a PlayStream.

A FilterStream is derived from PlayStream but also accepts an input PlayStream. FilterStreams are used to perform some operation on the input stream before passing its audio data to the requesting object through the 'WaveBuffer GetBuffer()' virtual method. The ConversionStream (uses the ACM API) is an implimentation of a FilterStream. The SpectrumAnalyzer is also a FilterStream that passes the input directly to the output but performs Fast Fourier Transformation on the audio data so it can be graphed as a spectrum analyzer. The Mixer is also a form of a FilterStream although it accepts many input streams and thus is derived from PlayStream.

Derive your own class from PlayStream or FilterStream and they will be compatible with the library and can be inserted into the stream chain at any point. For example, you may create your own FilterStream to perform echo cancellation on an input stream, or create a PlayStream that loads audio data from a database.

In the mixer demo, audio data starts from the wave source stream (WaveStream) into the Audio Compression Manager (ACM) stream (ConversionStream) then into the mixer stream (PlayStream), then the output of the mixer stream is connected to the Player. The Player requests buffers from its input stream, it is the end of the stream and is thus the consumer. The requests are directed through the stream chain as they are requested from the consumer.


NOTICE: Code from the FFTW Project has been used in the making of this project. This excellent code is used to generate the Spectrum Analyzer for the AudioClasses library. Here is the introductory statement found on the FFTW web site:
    'FFTW is a C subroutine library for computing the Discrete Fourier Transform (DFT) in one or more dimensions, of both real and complex data, and of arbitrary input size. We believe that FFTW, which is free software, should become the FFT library of choice for most applications.'
Thanks guys! ;-)

Using the AudioClasses Library:

First, you must declare a mixer object to contain the mixing sources and a player to send the mixed audio to the sound device.

   /* the mixer target : the sound card */
   Player   m_player;

   /* our mixer control that contains the mixer stream */
   CMixerListBox   m_channels;

Following is the relevant code in the mixer demo that initializes the mixer:

   /* set channel listctrl icons */
   m_channels.SetVolumeIcon(AfxGetApp()->LoadIcon(IDI_VOLUME),
                      AfxGetApp()->LoadIcon(IDI_MUTEDVOLUME));

   /* set channels custom listctrl to point to mixer */
   m_channels.Popup(IDR_MIXERPOPUP);

   /* set the mixer as the play stream */
   m_player << m_channels;

You can load some files into the mixer with the following, or use the AddStream if you have an existing stream:

   /* load some files into the mixer */
   m_channels.Load("c:\\sample1.wav");
   m_channels.Load("c:\\sample2.wav");
   m_channels.Load("c:\\sample3.wav");

Now you can start playing the mix:

   /* start playing */
   player.Play();

Updates

November 28, 2001
  • Memory leak causing application to freeze.
  • Some 'missing file reports' due to bad links in project file.

Downloads

Download demo project - 2,575 Kb
Download source - 88 Kb


Comments

  • Detected memory leaks!

    Posted by HpyWho on 04/04/2006 10:13am

    when i run, i detected memory leaks,can you help me? very thanks.

    Reply
  • Producing a single *.wav file output

    Posted by cain2143 on 11/30/2004 11:09pm

    After mixing or adding all the *.wav files into the Player object, how may I use the AudioClasses to output a single *.wav file from the Player?

    Reply
  • I found a problem when re-plug the USB audio device.

    Posted by dbckdrb on 07/19/2004 08:14am

    If you have a USB audio device, then you can make the same situations. Here is a steps. 1. Load a wave files. 2. Unplug the USB audio device while playing 3. Wait while play stops. 4. Plug the USB audio device. 5. Check! Is that mixer device list up? (My system can't shows the mixer but shows device) Is this problem out of bound of this program? (maybe)

    Reply
  • How to convert Level value to dB ?

    Posted by Legacy on 01/21/2004 12:00am

    Originally posted by: wyw

    Hi,

    Is there a way to convert the Level value return by the Mixer into dB ?

    Thank You,
    wyw

    • is very easy

      Posted by alainstgt on 12/07/2005 11:10am

      the dB value is 10*log10(level/reference level). In acoustics the refence sound pressure is 0.00002 Pa (Pascal), the reference level the square of that value. Since an addition is performed much faster than a division, you can change the formula like following: 10*(log10(level)-log10(reference level)). With rhe previous mentioned value, you get log10(reference level)= 93,9794 dB, which is usually rounded to 94 dB. So thr formula to get the dB level is: dB = 10*log10(sound pressure level) - 94! thats all. Note that what is commonly named the level, is in a strenght way not the level, but I used your terminology to not confuse.

      Reply
    Reply
  • Getting Left/Right channel level values

    Posted by Legacy on 01/20/2004 12:00am

    Originally posted by: wyw

    Hi,

    How do you go about extracting the individual left and right channel peak level value from a playing wave file?

    m_channels.level //This seem to be the combined result of left and right

    Thank You,
    wyw

    Reply
  • Help with wave mixing algorithm

    Posted by Legacy on 01/19/2004 12:00am

    Originally posted by: Ashley McGilvery

    Hi would you be able to describe in words the algorithm for mixing the waves. The one I am using at home is to add the samples and devide by the number of tracks. This works although the volume seems to be belong unity level.

    Reply
  • Problem compiling with Visual Studio 7

    Posted by Legacy on 01/10/2004 12:00am

    Originally posted by: cslick

    Hi Colin,

    I see that you created your project with Visual C++ 6, but I'm trying to build in VC++ 7 and getting an error: "error C3803: 'bool:Property::AsString()': property has a type which is incompatible with one of its accessors 'CString&Property::asstring(void)'. The problem is on line 56 of "Property.h". I am very new to windows programming - any clue how to fix this error? Thanks.

    Reply
  • Mixing properties

    Posted by Legacy on 09/21/2003 12:00am

    Originally posted by: Lee

    Thanks for your short tutorial on compiling.
    A few days ago you replied to my request for help on the filterstream(echoes) & I hope you can help me once again.

    I wanted to create an echo that is one second later. So I altered the getbuffer virtual method of wavestream by reading data from the audio file twice & putting them in 2 different buffers:

    1)fread from file into buffer.data (of wavebuffer buffer)

    2)fseek -11*RequestSize from SEEK_CUR (1 sec offset)
    - fread from file into buffer1.data(of wavebuffer buffer1)

    3)fseek 10*RequestSize from SEEK_CUR(return to original pos)

    4)return buffer2 (which mixes buffer & buffer1)

    I have created 3 buffers- buffer which contains the current audio data, and buffer 1 which contains audio data 1 secs back. buffer 2 is supposed to be a mix of the 2 buffers.

    I have read how u mix the streams in the mixer & frankly it was difficult for me to understand (I am still a beginner). Do you mind giving me advice on how I can combine the 2 buffers' data & store them into buffer2 ?

    Please help me in this.

    Thanks a million.


    regards,
    Lee

    Reply
  • Can you help me...

    Posted by Legacy on 09/16/2003 12:00am

    Originally posted by: Lee

    Hi,

    So sorry to trouble you. Previously I was doing a project using your audio classes. What I did was just copy the header files for the various classes into my external dependencies & the dAudiolib.lib.It worked. However I find I have trouble trying to add more functions to the program.

    I was trying to add the function waveOutSetPitch in Player.cpp but cannot find it in my project directories. So I copy it over & edited it. However there is a "unexpected end of file while looking for precompiled header directive" problem when I was compiling Player.cpp. I tried compiling your original player.cpp in your demo project, & the same thing happens.

    Am I missing out on something here? Did I forgot to do something.

    Your help is appreciated.


    Thanks in advance,
    Lee

    Reply
  • Filter Stream help.

    Posted by Legacy on 09/05/2003 12:00am

    Originally posted by: Lee

    I am trying to find a way to add some other functions to the conversion stream. Anybody knows of any examples (such as adding echoes, reverberation or audio filters) that can manipulate the buffers in the stream.

    Thanks.


    Thank You. Mr Colin. I will try that out.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • As all sorts of data becomes available for storage, analysis and retrieval - so called 'Big Data' - there are potentially huge benefits, but equally huge challenges...
  • The agile organization needs knowledge to act on, quickly and effectively. Though many organizations are clamouring for "Big Data", not nearly as many know what to do with it...
  • Cloud-based integration solutions can be confusing. Adding to the confusion are the multiple ways IT departments can deliver such integration...

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date