Prof.Dr.Godfried-Willem RAES

<GMT> Library Reference Manual: Module 8: AUDIO related procedures and functions


Introduction to <GMT> <Index > <Introduction> to the harmony library functions <General Functions> <midi functions>
  <Fuzzy Functions> <Analysis Functions> <Acoustical Functions> <audio functions>
  <Visualisation Functions> <File Management> <Psychological Functions> <rhythm functions>

 CHAPTER 8: GMT_AUDIO

Since our release version 4.20, this module went through an almost complete rewrite. Thus we changed most of the audio related functions. Not only the functions became easier to use, but also they are now quite a bit more flexible.

Internally the GMT_Audio support makes use of a maximum of 16 audio channels (tracks). Each channel can be configured for input or output (recording / playback) and makes use of an individual Waveheader structure, residing in the global array WavHdr(0 TO 15). The sample data are stored in 16 individual dynamic global dword arrays AudioTrack0() to AudioTrackF() residing in gmt_lib.dll. If the sum of data in these tracks exceeds the memory of your PC, you may encounter serious problems. GMT does not check for this condition. Be carefull and warned. As yet, continuous playback (as well as continous recording) of these mixed 16 tracks is only possible on reasonably fast PC's. Slower PC's may suffer from glitches. We are working on this problem...

The declarations for all audio related procedures and functions residing in the library g_lib.dll and g_wave.dll can we found in g_lib.bi and g_wave.dll. This file has to be included in your source to get access to the library functions. The source code for the functions explained in this chapter is in the following files:

g_wave.inc & g_wave.bi contains only audio related tasks that can be integrated in the GMT context. Please download the zip files with the complete source code. Once unzipped, these files will be found on your pc. Scanning through the source code will likely clarify questions that we left -by lack of time and collaborators- unanswered in this brief reference guide. To fully understand the source code it is mandatory to have access to the MSDN documentation for the Win32api. (We use the documentation packed with Visual Studio 6.0 from Microsoft, but now it is also available online). Also some understanding of digital audio processing comes in handy. Note that some functions and procedures build on functions and procedures included in out math library. (modules g_math.inc, g_math.bi)

Since version 5.00 we have added support for real time granular synthesis in this function library. Demos are available on request. Also the mci functions for CD access have been changed as we placed them in the library. FFT and DFT function have been revised since version 5.46.

Procedures for handling audio I/O in <GMT> using the Win32Api


List of functions and procedures:

Audio/Wave related procedures and functions:

all simple numeric parameters are passed by value (unless explicitly noted otherwize). Structures (types), complete arrays and strings always by reference.

AppendAudioTrack (track0, Track1)
 
BlankAudioBuffer (w AS WAVEHDR)
CopyAudioTrack (Track, duur AS LONG)
CheckAudio (Au AS AudioType, App AS ApplicationType)
GetAudioFormat ()
GetAuxPorts (mp() AS STRING)
GetAvailableAuxDevs$ ()
GetAvailableWaveInputDevs$ ()
GetAvailableWaveOutputDevs$ ()
GetFreeAudioTrack () AS LONG
GetWaveInPorts (mp() AS STRING)
GetWaveOutPorts(mp() as STRING)
Mix2Tracks (Track1 as long, Track2 as long)
MixChunk (buftoggle) [ not exported]
OpenAudioInputDevice (long) as long
OpenAudioOutputDevice (long) as long
PlayAudioTrack (TrackNr AS LONG, flags AS DWORD) AS LONG
PlayWaveFile (filenaam as ASCIIZ, flags AS WORD) AS LONG
PrepareWaveFunctions (WavHdr() AS WAVEHDR,TrackStatus AS AudioTrackStatus)
ReadWaveData (filenaam AS ASCIIZ) AS LONG
RecordAudioSample (duur AS DWORD) AS LONG
RetrieveSample (duur as dword) AS LONG
RetrieveInputwave(param as dword, Sp()) as LONG
ReportError (id AS INTEGER) [internal]
ReportWaveInError() [internal]
ReportWaveOutError() [internal]
ReSizeAudioTrack (TrackNr AS LONG, duration as dword) AS LONG
SaveAudioTrack (filenaam AS ASCIIZ, tracknumber as LONG) AS LONG
SetAudio (au as audiotype)
SizeAudioTrack (tracknumber AS LONG, duration as dword) AS LONG
StartAudioStreamThread ()
StartWaveOutStream (param AS DWORD) AS LONG
StartWaveInStream (param) AS LONG
TrackDuration (TrackNr AS LONG)
WaveDuration (BYREF Wavebufferheader AS WAVEHDR) AS DWORD
WaveDFT (Track AS LONG, offset AS DWORD, channel AS DWORD, Sp!())
WaveDFTHiRes (Track AS LONG, offset AS DWORD, channel AS DWORD, Sp!(). lb as long, ub as long)
Track2Seq ( track AS LONG, lr AS LONG) AS STRING
Track2SeqEx ( track AS LONG, lr AS LONG, granul AS LONG, NrNotes AS LONG, lfreq as long, hifreq as long) AS STRING
WriteAudioTrack (filenaam AS ASCIIZ, Wh AS WAVEHDR) AS LONG

callback procedures:

ProcWaveInCallBack (long,long,dword,long,long) AS LONG [not exported]
ProcWaveOutCallBack (long,long,dword,long,long) AS LONG [not exported]

modulation functions and procedures:

AmplitudeModulate(tracknr&,fl!,fr!,d1!,dr!)AS LONG
Crossmodulate (WAVEHDR)
CrossTimeModulate (BYREF Wavebufferheader AS WAVEHDR)
DeglitchStart (WAVEHDR)
DeglitchTail (WAVEHDR)
DeglitchTrack (Tracknr AS LONG)
FadeTrack (Tracknr AS LONG, fadeInTime AS DWORD, fadeoutTime AS DWORD)
LTrimWave (WAVEHDR,noiselevel)
RemoveDC (WAVEHDR)
NormalizeWave (WAVEHDR,procent as dword) AS LONG
Reverse (BYREF WaveIbufferheader AS WAVEHDR, BYREF WaveObufferheader AS WAVEHDR)
Ringmodulate (WAVEHDR, freqleft, freqright)
RingModulateTrack (Track,freqleft,freqright)
RTrimWave (WAVEHDR,noiselevel)
TrimTrack (TrackNr AS LONG, noiselevel)
TrimWave (WAVEHDR, noiselevel)
Varispeed (WAVEHDR,WAVEHDR)
WaveAddReverb (BYREF Wb AS WAVEHDR, NulT AS DWORD, faktor AS SINGLE)
Wave2Enveloppe (BYREF Wh AS WAVEHDR, Env() AS SINGLE, factorial AS STRING *5, ch AS STRING * 1, linlog AS STRING *3)
WaveOutFaders () [gmt_wave]
AuxFaders () [gmt_wave]
Granular Synthesis functions and procedures:
CalcNrOfGrains ( tracknr AS LONG, Grainlength AS DWORD) AS DWORD
GranulateTrack (track AS LONG, Env AS DWORD, BYREF GranAr() AS INTEGER)
GranuSynth (BYREF GranAr() AS INTEGER, stap AS DWORD, stretch AS SINGLE) AS LONG
GranuSynth2 (BYREF GranAr() AS INTEGER, overlapfactor AS SINGLE, duration AS DWORD) AS LONG
StretchTrack (track AS LONG, Grainlength AS DWORD, stretch AS SINGLE) AS LONG
GranPitchShift (track AS LONG, interval AS SINGLE) AS LONG

Wave generators and oscillators:

GenerateFMdiadWave(f1!,f2!,level!,pan!,d as dword) AS LONG
GenerateHarmWave(H AS HarmType,pan?,d as dword) AS LONG
GenerateSineWave(Note?,Velo?,Pan?,d as dword) AS LONG

CD-Related procedures and functions: (code module g_mci.*)

CloseMCIDevice (devID AS LONG)
ReportMCIError (dwError AS LONG)
MCI_MAKE_TMSF (track AS BYTE, minutes AS BYTE, seconds AS BYTE, frames AS BYTE) AS DWORD
PlayCDChunk (StartPoint AS DWORD, StopPoint AS DWORD)
PlayCDTrack (Track AS BYTE)
PauseCD ()
StopCD ()
CueCD (Seekpoint AS DWORD)
EjectCD ()
CloseCD ()
GetCDDeviceCaps ()
GetCDTrackDuration (Tracknr AS DWORD) AS DWORD
GetCDDuration () AS DWORD
MCIproc (hWnd AS LONG, wMsg AS LONG, wParam AS LONG, lParam AS LONG) AS LONG
MakeMCIWindow ()
XLAT_TMSF_2_MS (TMFS AS DWORD) AS DWORD
SetMCI (BYREF MCIiD AS MCIdevicetype, BYREF AudioCD AS AudioCDtype)

Windows Mixer related functions: (module g_wmix.inc)

LoadMixerSettings(fn AS STRING) AS LONG
SaveMixerSettings (fn AS STRING) AS LONG
WinMix_Mute(BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD, BYVAL mute AS LONG)
WinMix_SetVolume(BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD, BYVAL l AS WORD, BYVAL r AS WORD)
WinMix_Rec_Select(BYVAL hMix AS DWORD, BYVAL component AS STRING)
WinMix_Rec_SetVolume(BYVAL hMix AS DWORD, componenttype AS DWORD, BYVAL l AS WORD, BYVAL r AS WORD)
WinMix_GetMute(BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD)
WinMix_GetVolume(BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD, BYREF l AS WORD, BYREF r AS WORD)
WinMix_Rec_GetSelect(BYVAL hMix AS DWORD)
WinMix_Rec_SetVolume(BYVAL hMix AS DWORD, componenttype AS DWORD, BYREF l AS WORD, BYREF r AS WORD)

Users & Reference guide

1. Audio-related functions and procedures

CALLBACKFUNCTIONS:

FUNCTION MCIproc (BYVAL hWnd AS LONG, BYVAL wMsg AS LONG, BYVAL wParam AS LONG, BYVAL lParam AS LONG) AS LONG

This function is the callback for all mci procedures and command. It is coupled to the hidden window created with MakeMCIWindow(). Users do not have to call this functions nor interfere with it in any respect.

ProcWaveInCallBack()

Callback procedure for wave input (audiorecording). This procedure sets and reads flags in the Audio structure. It takes care of unpreparing the wave input waveheader, saving samples to disk, playing audioinput as a delayline etc...

ProcWaveOutCallBack()

Callback procedure for wave output (playing).

Normally users do not have to call any of these functions in their own code, unless they want to automate the setup. The price for doing so however, is that the code becomes very dependent on the organisation of a particular pc and its hardware.


Initialization and Internal functions:

SUB MakeMCIWindow ()

This procedure makes an invisible window just used to implement the required callback window handle for MCI deviced under Win32. It is called whenever an MCI device is opened or selected in the opening menu.

SetMCI (BYREF MCIiD AS MCIdevicetype, BYREF AudioCD AS AudioCDtype)

This procedure is called by GMT on initialisation of MCI devices. It publishes essential pointers to the dll library such that it can access your mci devices and make them functional. If working in the GMT context the user does not need to call this procedure.

SUB ReportError (id AS INTEGER)

Allerts for errors with wave I/O functions and procedures. This procedure is part of the DLL and should not be called on its own.

SUB ReportMCIError (BYVAL hWnd AS LONG, dwError AS LONG)

Allerts for errors with MCI procedures. Used internally. This procedure is part of the DLL.

SUB CloseMCIDevice (BYVAL hWnd AS LONG, BYVAL devID AS LONG)

Closes an MCI device and invalidates its handle, ID. Releases the driver. This procedure is part of the DLL.

GetAvailableWaveInputDevs$ ()

Returns the available devices on your PC that can be used for waveinput. This function is called internally during setup.

GetAvailableWaveOutputDevs$ ()

Returns the available devices on your PC that can be used for waveplaying. This function is called internally during setup.

GetWaveInPorts (mp() AS STRING)

Returns the available devices on your PC that can be used for waveinput. This function is called internally during setup.

GetWaveOutPorts(mp() as STRING)

Returns the available devices on your PC that can be used for waveplaying. This function is called internally during setup.

FUNCTION StartWaveOutStream (BYVAL param AS DWORD) AS LONG

This function allows you to play tracks simultaneously instead of sequencial. However in the actual implementation you may still encounter glitches during playback, if your PC does'nt meet speed requirements. We are heavily working to get this straight... Sofar it works glitchfree only on very specific (and fast) machines and soundcards.

The function returns %True if succesfull, %False if unsuccessfull. If waveoutstreaming could not be activated because there where still audiotracks playing or queued up for playing, the function will returns a negative number corresponding to the number of playing/queued tracks. In the latter case you should poll the function until it returns %True.

Parameters are:

The function works in conjunction with MixChunk(togbuf) in the callback. We got it working without using dsound.dll, a library that presupposes the use of Microsoft foundation classes, too much overhead for our purpose... If readers are interested in trying to improve our approach, please feel free to contact the author.

MixChunk (buftog)

This is the internal DLL procedure performing the audiostreaming for a maximum of 16 simultaneous audiotracks. It should never we called directly by the user.

GetAudioFormat ()

Thus functions returns a pointer to the Audioformat structure used in the library.

SetAudio (au as audiotype)

This procedure should be called by GMT or its applications, to change flags in the audio structure AudioType.
We allow only setting of flags that can be set by the user application in GMT. Other flags are just updated on return.

GetAuxPorts (mp() AS STRING)

This procedure returns the available auxiliary devices as reported by Windows on the PC.

GetAvailableAuxDevs$ ()

Performs the same action as GetAuxPorts, but reports the results as a textblock that can be displayed in a window.

PrepareWaveFunctions (WavHdr() AS WAVEHDR, TrackStatus AS AudioTrackStatus)


Internal procedure called in InitGlobals in GMT. This way we know the structures as used in GMT in the DLL. Note that we wrote this in gmt_lib.bas:
GLOBAL pTrackStat AS AudioTrackStatus PTR ' - value initialized in callbacks for waveIN/OUT
GLOBAL pWbh() AS WAVEHDR PTR ' array of pointers to the the wavebufferheaders in GMT

StartAudioOutStreamThread () AS LONG

Internal function to start an audiostreaming thread. This function should not we called by users directly.

use: @pTrackStat.StreamOut = StartAudioOutStreamThread ()

StartWaveInStream (param AS LONG) AS LONG

This function starts continuous (streamed) audio input. If this function is on, recording takes place in streaming mode: continuous, using the properties for latency and buffering as set in the declared constants. (55ms input latency). Fluent continuous recording requires a reasonably fast PC. If the PC is not fast enough, glitches may be observed in the recordings.


WAVE AUDIO I/O PROCEDURES AND FUNCTIONS

AppendAudioTrack (track0 AS LONG, Track1 AS LONG)

Adds the second track to the end of the first track. The data in the second track is lost (track freed) on exit.

Mix2Tracks (track1 AS LONG, track2 AS LONG) AS LONG

This functions mixes two stereo audiotracks and rescales the result. The result will always be returned in the longest track passed. The other track will not be released on return, so the data will be preserved in the track passed.

CheckAudio (BYREF A AS AudioType,BYREF App AS ApplicationType)


This procedure should be called by GMT or its applications, in order to update the flags in Audio (as AudioType) with the values set in and used by the DLL.


BlankAudioBuffer (w AS WAVEHDR)

This procedure -residing in the DLL- can be used to fill an existing audiotrack with blanks without changing its size. With other words, it silences a track by replacing all samples with silence 'samples'. Note that this is not the same as freeing a track!


GetFreeAudioTrack () AS LONG

This function returns the next free audiotrack and available wavebufferheader. The tracknumber returned is 0 to 15. If no free track could be found, the function returns -1.

The function resets the .lpData, .dwBufferlength, .dwFlags in the corresponding WavHdr() structure and sets .dwUser to the free track.


NormalizeWave (Wh AS WaveHdr, procent AS DWORD) AS LONG

This function returns the maximum value encountered in the wave passed and rescales the amplitudes found according to the value passed in procent. If you pass 100% , the passed wave data will be normalized to 0dB on return.


FUNCTION SizeAudioTrack (tracknumber AS LONG, duration AS DWORD) AS LONG

This function allocates and locks memory for the audiotrack and should always be called prior to writing a track. It can also be used to delete a track and to free the memory it ate. In that case you have to pass %False for the duration. Otherwize, duration has to be expressed in milliseconds. The function set the WavHdr(tracknumber).dwbufferlength value as well as WavHdr(tracknumber).lpdata.

The function returns %False if an error occured. It returns %True if successfull.

Note: this function has been changed since version 4.20.


FUNCTION ReSizeAudioTrack (TrackNr AS LONG, duration AS DWORD) AS LONG


This function resizes an existing audiotrack preserving the existing content. Otherwize, parameters are as in SizeAudioTrack. The function sets the new size in Waveheader().dwbufferlength on exit of this procedure. If the new bufferlength is shorter than the original length, data is cut off. If bufferlength is not adjusted to a multiple of four bytes (a stereo sample in 16 bits), the function will correct this.

The function returns %False if an error occured. It returns %True if successfull.

Note: this function has been changed since version 4.20.


OpenAudioInputDevice (devnr AS LONG, TrackStatus AS AudioTrackStatus) AS LONG

OpenAudioOutPutDevice (devnr AS LONG, TrackStatus AS AudioTrackStatus) AS LONG

These functions are called by the GMT setup window, to return a handle to the wave input and output devices to be used by your application. They enable the respective callback functions in the dll:


FUNCTION PlayAudioTrack (tracknumber AS LONG, flags AS DWORD) AS LONG

Plays a memory buffer with audio samples through the opened wave output device. The handle should exist and be present in Audio.hWo prior to calling the procedure. An error will be displayed if this condition is not met. The track should contain valid wavedata.
This function prepares the wave output header and queues it up for playing. The user has to make sure the corresponding Audiotrackx() array contains suitable data. . So, WaveBufHead.lpData will contain a data pointer to valid audio samples and WaveBufHead.dwBufferlength will reflect the size of the sample buffer on return.
The result of the procedure is handled in the callback procedure for wave output. This procedure will unprepare the header.
The flags can be any combination of the following declared constants:
  • %WHDR_BEGINLOOP : marks the track as the beginning of an audio loop
  • %WHDR_ENDLOOP: marks the end of the track as the end of an audio loop
If only this track has to be looped, pass both constants combined through OR.
These constants are part of the Win32Api.
The function returns -2 if there was an fatal error.
If successfull it returns the tracknumber playing or queued up for playing. It sets the according flags in the structure TrackStatus.playing(tracknumber).
If the function returns -1, if the track could not be played because it is already playing , or inqueue, and if it can be called again with the same parameters.

FUNCTION PlayWaveFile (filenaam as ASCIIZ, flags AS WORD)AS LONG

Plays a *.wav file from disk through the sound device. If audio.hwo contains a valid wave-out handle, this will be used. If no wave output device was opened, the Win32 api function playsound will be used. Note that the format of the wave file passed must be consistent with the audio settings used on initialisation of GMT. The default is 16 bit PCM Stereo with a sampling rate of 44.1kS/s.
The flags can be one of , or a combination of following values:
Returns values for this function are:
0-15: track used for playing.
16: no wave handle, so the playsound function was used
-1: file was not played because device was still busy. You can call again.
-2: parameter or device error.

FUNCTION RecordAudioSample (duur AS DWORD) AS LONG

This procedure records an audiosample from the output of the recording mixer device installed on your PC. The user has to set up the sliders and controlls of this mixer prior to calling this procedure. Care has to be taken into avoiding feedback situations, which arrise easily if you open the microphone both on the recording and on the playback mixers...
Functions to manipulate the recording mixer under software controll are under investigation. [Help and code contributions highly appreciated...]
The duration of the sample to be recorded should be passed in the parameter duur and ought to be expressed in ms.
Since we wanted to implement recording/playback functions asynchronously, this procedure does not itself return the wavebufferheader. The result is handled in the callback function. If Audio.toDisk is set, the sample will be recorded to disk. The filename of the most recently recorded sample can be found in App.SampleFileName. The number can be traced in Audio.icnt. It is incremented automatically in the callback. If the audiodelayline flag is set, the recorded buffer will be copied and played back from within the callback, although this implementation may change in a future release.
The procedure will return with no result (-1) on following conditions:
If successfull the procedure will set the recording busy flag in the global structure TrackStatus.recordingtrack. The return value corresponds to the the audiotrack used for the recording. (0 to 15). The flag in Trackstatus.recording(tracknr) will be set to %True as well.
Example:
TrackNumber = RecordAudioSample (2000)
if successfull, this will return you (after 2 seconds of course....) a sample in AudioTrackx(), where x should be replaced by the hexadecimal digit corresponding to the tracknumber returned. The callback procedure unprepares the waveheader.
 
Application example for coding successive recording and playback.

RetrieveSample (duur as dword) AS LONG

This function returns immediately with the last recorded audio chunk.
If duur (duration expressed in ms) is larger than the audiobufferdepth (set by %AudioBufferSize) , the function will return a copy of the complete recordingbuffer. The function returns a tracknumber. If recording is not initialized and active, the function will fail.


RetrieveInputwave(param as dword, Sp()) as LONG

This function returns immediately with the last recorded audio chunk (always 55ms, or the value corresponding to the value set by the constant %lStreamInLatency). This function returns a normalized wave as an array of singles. You should pass a pointer to the array to receive the data in Sp(). DIM Sp(0 TO 0) as SINGLE, prior to calling this function meets this condition.
The parameter lets you specify some details:
param bit 0 = left channel wave data will be returned in Sp()
param bit 1 = right channel,
param bit 2 = mix of both channels
param bit 3 = apply LowPass for highest note 96 (midi units)

You can use the predefined constants, defining bit positions, as parameter values:
%LeftChannel = 0
%RightChannel = 1
%MixChannels = 2
%ApplyLowPass = 3

Audioinput streaming must have been initialized and active in order for this function to be successfull.


AuxFaders ()

Task prototype for real time fader controll of the auxdevice. The duration for the fade to be performed should be passed in Task().duur and should be expressed in milliseconds.
The tasknumber as well as the slider ID should be set prior to activating the task, in the global structure: AudioFaders.auxtasknr and AudioFaders.auxID.
This structure is filled and updated by the task in the following fields:
The endposition for the faders should be set in the fields:
The task will run until the duration passed is over. The sliders will move in linear intervals. The update rate is hardcoded at 12 steps per second.
When the duration and final positions of the left/right faders is reached, the task will stop and release itself.

WaveOutFaders ()

Task prototype for real time fader controll of the auxdevice. The duration for the fade to be performed should be passed in Task().duur and should be expressed in milliseconds.
The tasknumber as well as the slider ID should be set prior to activating the task, in the global structure: AudioFaders.playtasknr and AudioFaders.playID.
This structure is filled and updated by the task in the following fields:

The endposition for the faders should be set in the fields:

The task will run until the duration passed is over. The sliders will move in linear intervals. The update rate is hardcoded at 12 steps per second.
When the duration and final positions of the left/right faders is reached, the task will stop and release itself.

FUNCTION ReadWaveData (filenaam AS ASCIIZ) AS LONG

This function reads a 16 bit stereo wave file (44.1kS/s) from disk into a memory buffer (Audiotrack). If the function was succesfull, you can manipulate the data in memory in your code and, of course, play it back from memory to the waveoutput device selected. Of course you can also save it to disk again . The function selects automatically the next free audiotrack and sets the relevant parameters in WavHdr(x) . On return, the length of the buffer will be found in WavHdr(x).dwBufferlength, the wave data pointer in wavHdr(x).lpData. The audiotrack will be in AudioTrackx(), inside the DLL's workspace.
If successfull, the functions returns the tracknumber used (0 to 15) and filled, else, it will return -1.
The function does not check for validity of filename passed. So it is up to the user to do this prior to calling the function.
To play the file read, use the function PlayAudioTrack().

FUNCTION WriteAudioTrack (filenaam AS ASCIIZ, Wh AS WAVEHDR) AS LONG

(this function replaces the former: WriteWaveData (filenaam AS ASCIIZ, BYVAL lpWaveData,BYVAL dwWavedataSize AS DWORD, BYREF AudioFormat AS WaveformatEx) AS LONG)

This function -residing in the dll- writes wave data from a memory buffer to disk. The memory buffer should contain 16bit stereo PCM encoded 44.1kS/s audiosamples, as set on initialisation in the global structure AudioFormat. lpWaveData should contain a pointer to the sample data in memory, dwWavedataSize, should contain the exact length of the data. Both parameters can be found in the .lpData and .dwBufferlength fields of the WaveBufferHeader used.
Note that this function does not strictly require an audio track. Any buffer with audio data can be saved. To save audiotracks it is advised to rather use the function SaveAudioTrack (), since it checks more conditions and internally calls WriteWaveData in any case. The Audioformat structure is normally filled in GMT, where it is declared as global. It is not global inside the dll however, its settings should be passed to the DLL using the procedure SetAudio (). You can retrieve flags set in the dll using the procedure CheckAudio ().
The function returns %True, if successfull. If unsuccessfull, the function returns %False. It does not change any flags in the TrackStatus structure.

FUNCTION SaveAudioTrack (filenaam AS ASCIIZ, tracknumber as LONG) AS LONG

This function does the same thing as WriteAudioTrack, but is much easier to use as you can suffice to pass a tracknumber as parameter directly. This function also checks conditions, such as the buffer being queued up for playing...
If successfull, the function returns %True.
If unsuccessfull, the function returns %False or -1. In case the returns value is %False, you should not retry calling the function with the same parameters, since there must have been an error. In the return value is -1, the track is still busy playing or queued up for playing. You may call the function again -in a thread or as a task- until it returns %True.

This function releases the track saved on return. Thus trackdata is lost. It sets all relevant flags in the TrackStatus structure.


FUNCTION CopyAudioTrack (track AS LONG, duur AS LONG) AS LONG

This function returns a copy of the track passed in a new track, returned by its number if successfull.


SUB Ringmodulate (WAVEHDR, freqleft, freqright)

This procedure implements a true and classic ringmodulator. The left channel is ringmodulated with a sinewave of frequency passed in freqleft. The right channel is ringmodulated with a sinewave of frequency passed in freqright. The calculation is performed in place, thus the procedure changes the input wavebuffer.

SUB RingModulateTrack (Track,freqleft,freqright)

This procedure implements a true and classic ringmodulator. The left channel of audiodata in the track passed is ringmodulated with a sinewave of frequency passed in freqleft. The right channel is ringmodulated with a sinewave of frequency passed in freqright. The calculation is performed in place, thus the procedure changes the input wavebuffer and passes the result in the track passed on entry.

SUB Crossmodulate (WAVEHDR)

This procedure ringmodulates the contents of the left channel, with the contents of the right channel in the wavebuffer passed. The result is returned in place as a 2-channel mono signal. The calculation is performed in place, thus the procedure changes the input wavebuffer. Internal processing uses 32 bits. The reduction to 16 bit happens after the multiplication.

SUB CrossTimeModulate (WAVEHDR)

This procedure ringmodulates the leftchannel audio data with the reversed right audio channel data passed in the waveheaderbuffer. The procedure operates in place and overwrites the wavebuffer passed. The result is 2-channel mono.

SUB Reverse (BYREF WaveIbufferheader AS WAVEHDR, BYREF WaveObufferheader AS WAVEHDR)

This procedure returns a backwards copy of the audiodata passed in the first wavebuffer. Source and destination must have exactly the same length! The result remains stereo, if the input is.

SUB Varispeed (WAVEHDR,WAVEHDR)

This procedure implements a simple stereo varispeed. The output, the second wavehdr, should go into a new audio track. This serves as a code prototype for a pitch sampler. It works by linear interpolation in the time domain. Pitchshift and Timestretch functions, based on time-domain granular synthesis are included in the library as well.
Usage:


1.- The WaveIbufferheader should exist in a created and valid audio track. Say, you have an audiotrack as i. So, WavHdr(i).dwBufferlength will reflect the size of the input data.
2.- Then , get a free new audiotrack for the result:
NewTrack = GetFreeAudioTrack
3.- check NewTrack (must be > -1)
4.- Now set the size for the wavebuffer in the new track:
WavHdr(NewTrack).dwBufferlength = DWORD(WavHdr(i).dwbufferlength * faktor!)
If faktor! is > 1 then, we will slow down and stretch the original sound, if factor! is taken < 1 , then we will speed up and shorten the original sound. We do not pass factor as a parameter, since it is safer to recalculate in from the proportion of the size of the respective buffers. It will be clear that if factors derived from 12th root of 2 are used, we can implement a 16bit stereo sample player quite easily using this procedure...


FUNCTION AmplitudeModulate(tracknr&,fl!,fr!,d1!,dr!) AS LONG

This function performs amplitudemodulation on the two channels of the track passed. The modulation frequencies should be passed in fl! and fr! (resp. for the left and right channels) and the modulation depth (normalized to 0-1) in dl! and dr!, again for the left and the right channels.


SUB DeglitchStart (Wh AS WAVEHDR)

SUB DeglitchTail (Wh AS WAVEHDR)

SUB DeglitchTrack (TrackNr AS LONG)

These procedures both return the wavedata contained in the wavebuffer (Wh) , unchanged but deglitched. The first procedure, removes possible glitches at the start of the waveform, by performing a sine-shaped very fast fade-in if the wave does not start on a zero cross.
The second procedures returns the waveform such that it always ends on a zerocross of the signals in both channels. Here again, a very fast sinusoidal fadeout is applied.
 

Deglitchtrack is a macro, calling both previous functions in a row. You only have to pass the appropriate track as a parameter.

SUB RemoveDC (Wh AS WAVEHDR)

This procedure calculates eventual DC offsets or residues in the waveform passed. If a DC-offsett is found, the entire waveform will be recalculated such that it disappears. The function is very important if the waveform data went through rectification, square rooting, exponentiation... and such more procedures.

SUB FadeTrack (Tracknr AS LONG,fadeintime AS DWORD, fadeouttime AS DWORD)

This procedure recalculates the wavedata such as to produce a fade-in over a duration given by fadeintime (expressed in milliseconds), and a fadeout at the end given by fadeouttime. If you want only one of both fades, you should pass %False as time parameter for the unwanted fade. If the sum of requested fade-times exceeds the length of the track, the fade will be evenly distributed over the entire track. If this happens with one of the durations set to zero, you will get a decrescendo or a crescendo respectively over the entire duration of the track.


FUNCTION LTrimWave (WAVEHDR,noiselevel AS WORD) AS DWORD

This function returns the number of bytes the wave data passed in wavehdr have been shifted to the left such that after calling the function, the new wave data allign exactly on the first occurance of a soundsample with absolute amplitude exceeding the noiselevel passed. The value returned by the function is required to resize the audiotrack.
Normal use of this function is:
 
FUNCTION RTrimWave (WAVEHDR,noiselevel AS WORD) AS DWORD
This function returns the number of bytes that may be cut of from the tail of the wavedatabuffer passed in WAVEHDR, since the samples contained are below the noiselevel passed. The function does not change the contents of the wavebuffer. Normal use of this function, whereby we cut of the tail below the noiselevel is:

SUB TrimWave (WAVEHDR, noiselevel AS WORD )

This procedures calls both the functions LTrimWave and RTrimwave in a row and returns the new length of the wavebuffer in the .dwbufferlength field of the waveheader. After calling the procedure the user should resize the audiotrack according to the new value. This call is mandatory!

Example:

SUB TrimTrack (TrackNr AS LONG, noiselevel as word)

[in the works]

This procedure performs TrimWave on the tracknumber passed and at the same time resizes the wavebuffer according to the result.


SUB Wave2Enveloppe (BYREF Wh AS WAVEHDR, Env() AS SINGLE, factorial AS STRING *5, ch AS STRING * 1, linlog AS STRING *3)

This procedure returns the enveloppe of the contents of the wavebuffer passed, in the form of a normalized unipolar data array. All values in the returned array are between 0 and 1. The passed wavebuffer is Wh, the first parameter. The returned normalized enveloppe array is dimensioned inside the procedure, so the user can suffice with an initialisation declaration such as:
DIM Env(0 TO 0) AS SINGLE.
This array should be passed by reference (Array pointer) and forms the second parameter for the procedure.
The following 3 parameters allow further control as follows:

factorial:

Since calculation of an enveloppe requires datareduction, and since the standard sampling rate we use in GMT is 44.1kS/s (defined in the declared constant %CD_SR) we can use any combination of divisors of this number as a suitable base for the reduction.
44100 S/s equals : (7^2) * (5^2) * (3^ 2) * (2^ 2), a number that can be represented as a factorial using a string format as:
"22220", where the 'digits' are ordered, as usual, msb first, lsb last. Each position of a character in the string reflects the value of the exponent of the corresponding prime number, except for the "0" value, representing the non presence of this divisor in the factorial.
This format, since exponents can only be 4-bit numbers, can only represent all numbers up to 2^15 (This would be written: "000F0"). If we limit the string length, it is not even a continuous representation. However, for our purpose, it seems perfectly well suited. To save users the calculation by hand, we made following lookup table:
Enveloppe sampling rate

(nr. of steps fer second of audio in the Env() array)

division factor used factorial string to be passed
7 6300 "12220"
14 3150 "12210"
25 1764 "20220"
49 900 "02220"
50 882 "20210"
75 588 "20120"
98 450 "02210"
100 441 "20200"
210 210 "11110"
11025 4 "00020"
22050 2 "00010"
44100 1 "00001"

ch:

This parameter (a single character) is used to allow you to specify to perform the calculation on either the left audio channel or the right channel, or on both together. Possible values are:

linlog:

This parameter allows you to request either linear conversion or logarithmic conversion. The string parameter can take two values:
"LIN", for linear conversion
"LOG", for logarithmic conversion.
In both cases the values returned in Env() will be normalized to 0 to 1. Thus, if you need a dB scale and knowing that the resolution is 16 bits, we could multiply the values with 96 to reflect a dBV scale.

SUB WaveAddReverb (BYREF Wb AS WAVEHDR, BYVAL NulT AS DWORD, BYVAL faktor AS SINGLE)

Using this procedure, it is possible to add reverb / echo to existing wave data contained in a given wavebuffer. To accomodate for the added length of a sound with added reverb, the user should provide the required space at the end of his sound data prior to calling the procedure. Obviously, this extra data space should be filled with zero's (silence).
The first parameter points to the input waveheader structure. The second parameter, NulT, is the time before the first reflection starts. This is proportionate to roomsize and should be expressed in milliseconds.
The third parameter, faktor, reflects the amount of reverb. If 1 is passed, the reverb is infinite and the wave might clip... If you pass larger values than 1, the procedure will limit them to 0.9999 to avoid overflows and positive feedback.


FUNCTION WaveDuration (BYREF Wavebufferheader AS WAVEHDR) AS DWORD

This function returns the duration of the audiobuffer expressed in milliseconds. It is assumed the wavebuffer is 16-bit stereo and 44100 S/s.

FUNCTION TrackDuration (BYVAL TrackNr AS LONG) AS DWORD

This function returns the duration of the track expressed in milliseconds. It is assumed the wavebuffer is 16-bit stereo and 44100 S/s.


Granular Synthesis Support:

This section was written in collaboration with Kristof Lauwers.

FUNCTION CalcNrOfGrains (tracknr AS LONG, Grainlength AS DWORD) AS DWORD

This function should be called in order to prepare and dimension the array of grains required for the GranulateTrack procedure.
Given a grainlength, expressed in number of samples, it calculates the number of grains the track passed contains. Normaly in you code, the function is followed immediately by:

DIM GranAr(0 TO NrGrains -1, 0 TO GrainLength) AS [LOCAL][STATIC][GLOBAL] INTEGER

whereafter the procedure GranulateTrack can be called


SUB
GranulateTrack (BYVAL track AS LONG, BYVAL Env AS DWORD, BYREF GranAr() AS INTEGER)

This procedure splits a track in grains of length = Grainlength, and returns all the data in GranAr(), as explained before. The Env parameter allows you to select from a couple of build in windowing function applied to each of the grains.
Env = 1 applies as short linear fade over 240 samples. The window is simple trapezoidal.
Env = 2 applies a standard hanning window
Env = 3 applies a triangle window
Env = 4 applies a beta curve window with parameters 3,3. (cfr. math library) Internally the procedure examines the sizes of GranAr() to retreive the number of grains as well as the grainlength in samples:
NrGrains = UBOUND(GranAr,1) + 1
Grainlength = UBOUND(GranAr,2) + 1


FUNCTION
GranuSynth (BYREF GranAr() AS INTEGER, BYVAL Stap AS DWORD, BYVAL stretch AS SINGLE) AS LONG

This function eturns a track filled with the result of your granular synthesis based on the grains passed in GranAr(). GranAr() should have been prepared with GranulateTrack() prior to calling this function. The stap parameter is the number of samples, the granusynth steps on each iteration. (overlap). The lower this value the longer the procedure needs to calculate and the higher the intermodulation frequency in the result.
Reasonable values are 64 - 2048 , however you should make sure the value if always larger than or equal to half the grainsize used.


FUNCTION
GranuSynth2 (BYREF GranAr() AS INTEGER, BYVAL overlapfactor AS SINGLE, BYVAL duration AS DWORD) AS LONG

Another function to implement granular synthesis, returning a wave data track. Here again, the graindata must be passed in the GranAr() array prepared with GranulateTrack.
The overlapfactor is a parameter used to steer the amount of grain overlapping in the calculation. Values < 0.5 are illegal; these would create weird electronic artefacts...
overlapfactor: 0.5 is classic as used for timestretching.
Overlapfactor = 1 , means no overlapping, grains in succession in the wave.
Overlapfactor > 1 leaves holes between the grains.
Duration parameter: duration of the wavesound you want to generate (expressed in ms)
This function generates two identical channels (left=right) and returns the tracknumber.


FUNCTION
StretchTrack (BYVAL track AS LONG, BYVAL Grainlength AS DWORD, BYVAL stretch AS SINGLE) AS LONG

This function performs time stretching and compression of an audio track passed. The pitch remains unchanged. The quality and intermodulation distortion depends on the grainlength value passed. The amount of time stretching should be passed in the stretch parameter. Thus passing 2 will make the original track twice as long. 0.5 will make it half as long.
 


FUNCTION
GranPitchShift (BYVAL track AS LONG, BYVAL interval AS SINGLE) AS LONG

This function returns a track containing a pitchshifted version of the track you passed on input, maintaining the original duration.
The interval should be specified as a note-interval + optional fraction. The midi-system is used, so a unit corresponds to a musical semitone in the system of equal temperament. Thus +6 , transposes the wave a triton upwards, -6 , a tritone downwards.
'+ 8.3, transposes 8 semitones and 30 cents upwards., etc...
The limits for interval are +63 and -63. The ceiling is performed internally if you would pass values beyond this range. Internally, this function uses granular synthesis to perform the pitchshift. The grainlenght is constant and taken as 1024 samples.

Wave generators and oscillators:

These functions as now, serve mainly for testing puposes. In the near future we might expand them and even add audiogenerators from C-Sound, including gramular synthesis here.

FUNCTION GenerateFMdiadWave(f1!,f2!,level!,pan!,d as dword) AS LONG

This function returns a wave containing f1! and f2! frequencies (passed in Hz) synthesised with FM synthesis. The panning should be passed as a normalized value ranging from 0 to 1. The value 0.5 gives the same signal on both channels. The duration must be specified in ms. The function returns a tracknumber.

FUNCTION GenerateHarmWave(H AS HarmType,pan?,d as dword) AS LONG

This function performs a form of additive synthesis: all notes passed in Har.vel will be present in the wave returned by its tracknumber. The duration should be specified in ms.

FUNCTION GenerateSineWave(Note?,Velo?,Pan?,d as dword) AS LONG

This function returns a sine wave on both channels of the track returned. The parameters are as usual in midi synths, hence limited to 7 bits. The duration of the sinewave should be expressed in ms. The returned wave is full 16 bits, 2 channel.


AUDIO CD PROCEDURES AND FUNCTIONS (dll source code in g_mci.inc & bi)

SUB PlayCDChunk (StartPoint AS DWORD, StopPoint AS DWORD)

Plays a section of a CD. It lets the user start at any point in the CD. The handle is set on opening the device in MCIid.h. The values for StartPoint and StopPoint should be calculated using our function MCI_MAKE_TMSF (track AS BYTE, minutes AS BYTE, seconds AS BYTE, frames AS BYTE) AS DWORD. You are responsable for limiting the values to whats possible for the CD inserted in the drive. The number of tracks can be found in AudioCD.NrTracks, a global structure.


SUB PlayCDTrack (Track AS BYTE)

Plays a complete track from an audio CD. The procedure will release the driver only after the track has stopped. The mci window handle should be set to MCIiD.h. This is done on opening the mci cd device. The number of tracks can be found in AudioCD.NrTracks, a global structure.


SUB PauseCD ()

Pauses playing of a CD track or chunk. It does not release the device handler.


SUB StopCD ()

Stops the playing CD and releases the driver for a new play command.

SUB CueCD (Seekpoint AS DWORD)

The Seekpoint parameter should be formatted with MCI_MAKE_TMSF (track AS BYTE, minutes AS BYTE, seconds AS BYTE, frames AS BYTE) AS DWORD prior to calling this function. This procedure sets the CD-device to the passed position. During the seek operation, all audio-out is inhibited! Note that this can take up to 1500ms on some drives. This procedure should be used to cue up a CD such that it starts immediately on a subsequent play command. Once cued up, the CD starts in a minimum of time. CD timing constraints are bound to the hardware and out of control of this (and any) software. If your requirement is to cue up the CD to either the very beginning or the very end of the inserted audio CD, you can pass the special constants in Seekpoint:

The constants are defined in the Win32 Api. To make memorizing easier, we provided two aliases (with the same value):

SUB EjectCD ()

Ejects the CD in the drive and invalidates the medium bound parameters. Not all drives support software controlled eject. The user will be notified of the function is not available. As flag will we set in the audioCD structure as well.


SUB CloseCD ()

Closes the CD drive and updates the medium bound parameters. The procedure only supports audio CD media.Not all drives support software controlled close of the tray. The user will be notified of the function is not available.


SUB GetCDDeviceCaps ()

Called on initialisation of the CD device in GMT's main setup window. It fills the structures MCIid.h, MCIid.CDid, AudioCD.NrTracks etc... The relevant structures can be found in GMT_TYPE.BI

FUNCTION GetCDTrackDuration (TrackNr AS BYTE) AS DWORD

Returns the duration of a given CD track. Not all CD drives support this MCI function call! You will be notified with a message if your driver does not support the function. The function returns a value expressed in ms.


FUNCTION GetCDDuration () AS DWORD

Returns the total playing duration for the audio CD inserted in the drive. The return value is expressed in seconds.

FUNCTION MCI_MAKE_TMSF (track AS BYTE, minutes AS BYTE, seconds AS BYTE, frames AS BYTE) AS DWORD

FUNCTION Xlat_TMSF_2_ms (TMFS AS DWORD) AS DWORD

Creates the numeric parameters required to use with PlayCDChunk (BYVAL hWnd AS LONG, StartPoint AS DWORD, StopPoint AS DWORD) as well as CueCD(). This function is complemented with Xlat_TMSF_2_ms, converting a TMSF coded number into a value expressed in ms.


WaveDFT (Track AS LONG, offset AS DWORD, channel AS DWORD, Sp!())

Does a FFT transform over 1024 samples on the given track, starting from given offset. Make sure the track contains enough samples! For a channel value of 0 the left channel of the track will be used, for a value of 1 the right. The normalised result is returned in the array Sp!(). This array must be dimensioned (0 to 512) before this function is called. The values in the array represent the relative strength of 42.98 Hz width frequencybands. When this function is called the first time it creates a lookup table, wich takes some time. Subsequent calls will be fast enough for real time use.

WaveDFTHiRes (Track AS LONG, offset AS DWORD, channel AS DWORD, Sp!(), lb AS LONG, ub AS LONG)

This function is similar to WaveDft, but has a resolutin of 4096 samples. The Sp!() array must be dimensioned (0 to 2048) and will represent 10.475 Hz width frequencybands. Lb and ub represent the lower and upper boundary of the part of the Sp!() array that you want to be filled in. It is recommended to limit this when possible as computing all 2048 bands takes a lot of time! Note that the highest note on a piano lies in band 340, so you only need the results in higher bands if you are interested in the spectrum of a sound. Note that this function is too slow for real-time use.

Track2Seq ( track AS LONG, lr AS LONG) AS STRING

Converts an audiotrack to a 'Seq' string (cfr. SEQ file format). The result has a 1 second resolution. This function uses a low resolution DFT algorythm.

Track2SeqEx ( track AS LONG, lr AS LONG, granul AS LONG, NrNotes AS LONG, lFreq as long, hFreq as long) AS STRING

This function is similar as Track2Seq, but it uses a higher resolution DFT transform and thus has a higher precision. Granul determines the rythmic granulation wanted, expressed in notes / second, NrNotes is the maximum number of simultaneous notes in the result, lFreq and hFreq are the upper and lower boundaries of the frequencyrange taken into account. Limiting this range will speed up the function. Not that this function is very slow and it is not suitable for real-time use.


WINDOWS MIXER RELATED PROCEDURES AND FUNCTIONS (dll source code in g_wmx.inc & bi)

WinMix_Mute (BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD, BYVAL mute AS LONG) AS LONG

Mute or unmute a line in a windows mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. Componenttype is the windows constant for the componenttype of the line you wish to mute. Set 'mute' to 1 to mute a line, to 0 to unmute a line. The function returns false if succeeded, otherwise the windows error value. This function wil not work on the windows recording mixer, where you have to select a line with the function WinMix_Rec_Select

WinMix_SetVolume (BYVAL hMix AS DWORD, componenttype AS DWORD, BYVAL  l  AS WORD, BYVAL  r  AS WORD) AS LONG

Set The volume for a line in a windows mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. Componenttype is the windows constant for the componenttype of the line for wich you wish to change the volume. l / r is the volume (in percent) of the left / right channel. If you give a different value for l and r the panning slider in the mixer will automaticly be adapted. When the mixer doesn't support separate control for the left and right channel, both channels are set to the value in l . This function will not work on the recording mixer, where WinMix_Rec_SetVolume should be used.

WinMix_Rec_Select (BYVAL hMix AS DWORD, BYVAL componenttype AS STRING) AS LONG

Select a line in the windows recording mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. Unlike in the other mixer functions, componenttype here is a string indicating wich line you wish to select. You can select only one line at a time.

Valid components are:

component:selects:
"MIDI"internal midi synth output
"CD"CD-player output
"LINE"line level input
"MIC"microphone input
"AUX"auxiliary device
"DAT"DAT output
"TELEPHONE"  telephone/modem output
"VIDEO"sound output from video
"MIX"playing mixer output

 

WinMix_Rec_SetVolume (BYVAL hMix AS DWORD, componenttype AS DWORD, BYVAL  l  AS WORD, BYVAL  r  AS WORD) AS LONG

This function is similar to WinMix_SetVolume, but controls the volume in the recording mixer in stead of the playing mixer. The same componenttype constants can be used.

WinMix_GetMute (BYVAL hMix AS DWORD, BYVAL componenttype AS DWORD) AS LONG

Returns the mute status of a line in a windows mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. Componenttype is the windows constant for the componenttype of the line you wish to mute. This function returns 1 if the line is muted, 0 if it is not muted, or -1 is the mute status could not be retrieved.

WinMix_GetVolume (BYVAL hMix AS DWORD, componenttype AS DWORD, BYREF  l  AS WORD, BYREF  r  AS WORD) AS LONG

Get the volume for a line in a windows mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. Componenttype is the windows constant for the componenttype of the line for wich you wish to change the volume. l / r will be filled in with the volume (in percent) of the left / right channel. This function will not work on the recording mixer, where WinMix_Rec_GetVolume should be used.

WinMix_Rec_GetSelect (BYVAL hMix AS DWORD) AS STRING

Find out wich line is selected in the windows recording mixer. hMix is the handle to the mixer, wich in <GMT> will usually be gh.wMix. This function returns a string that indicates wich component is selected (see table below) Only one line can be selected at a time.

Return values are:

return value:selected:
"MIDI"internal midi synth output
"CD"CD-player output
"LINE"line level input
"MIC"microphone input
"AUX"auxiliary device
"DAT"DAT output
"TELEPHONE"  telephone/modem output
"VIDEO"sound output from video
"MIX"playing mixer output
"NONE"no line selected
"UNDEFINED"function failed to retrieve wich line is selected

 

WinMix_Rec_GetVolume (BYVAL hMix AS DWORD, componenttype AS DWORD, BYREF  l  AS WORD, BYREF  r  AS WORD) AS LONG

This function is similar to WinMix_GetVolume, but returns the volume in the recording mixer in stead of the playing mixer. The same componenttype constants can be used.

LoadMixerSettings (filename AS STRING) AS LONG

Loads settings for the windows mixer, as written by SaveMixerSettings, from a file. The function returns %true if succeeded.

SaveMixerSettings (filenamen AS STRING) AS LONG

Saves the current Windows mixer settings to a file. The file is supposed to be formatted like the gmt.ini file. If the file does not exist yet a new file will be created. If there were allready mixersettings stored in this file they will be overwritten. Otherwise a new section will be added just before the "[EOF]" string. The start of this section will be indicated by "[MIXER]", the end by "[MIXER_END]". Do not change this mixersettingsmanually unles you know what you are doing! Consult the sourcecode in g_wmix.inc to find out how the settings should be formatted. The function returns %true if succeeded.

 

Valid componenttypes for the windows mixer functions:

Windows constant:  selects device:
%MIXERLINE_COMPONENTTYPE_DST_DIGITAL digital device
%MIXERLINE_COMPONENTTYPE_DST_LINE line level out
%MIXERLINE_COMPONENTTYPE_DST_MONITOR monitor
%MIXERLINE_COMPONENTTYPE_DST_SPEAKERS speakers (= master volume)
%MIXERLINE_COMPONENTTYPE_DST_HEADPHONES headphones
%MIXERLINE_COMPONENTTYPE_DST_TELEPHONE telephone / modem
%MIXERLINE_COMPONENTTYPE_DST_WAVEIN wave in
%MIXERLINE_COMPONENTTYPE_DST_VOICEIN voice input
%MIXERLINE_COMPONENTTYPE_SRC_DIGITAL digital device
%MIXERLINE_COMPONENTTYPE_SRC_LINE line level in
%MIXERLINE_COMPONENTTYPE_SRC_MICROPHONE microphone
%MIXERLINE_COMPONENTTYPE_SRC_SYNTHESIZER internal midi synth
%MIXERLINE_COMPONENTTYPE_SRC_COMPACTDISC cd-player

Sample code for recording and playback without using audio I/O streaming:

SUB RecordPlayback
' demo code for a simple real time audio I/O task under GMT
' You have to select both wave input and output devices in the setup menu.

' The constant %demo_recplay must have been set elsewere to a suitable tasknumber.


STATIC jumpval AS DWORD
STATIC TrackNr AS LONG
LOCAL retval AS LONG
IF (Task(%Demo_RecPlay).switch AND %TASK_BUSY) = %d1 THEN EXIT SUB
IF Task(%Demo_Recplay).tog = %False THEN
IF ISFALSE Audio.hWi THEN Stoptask %Demo_RecPlay
CheckAudio Audio, App
Task(%Demo_Recplay).tog = %True
jumpval = %False
END IF

SELECT CASE jumpval
CASE %False
Task(%Demo_RecPlay).duur = 500 + (RND(1) * 5000) ' in ms
TrackNr = RecordAudioSample (Task(%Demo_RecPlay).duur) ' random recording durations...
SELECT CASE TrackNr
CASE -2 ' fatal error
StopTask %Demo_RecPlay
EXIT SUB
CASE -1 ' try again later...
jumpval = %False
Task(%Demo_RecPlay).freq = 10
EXIT SUB
CASE 0 TO 15
' optional: Audio.ToDisk = %True ' set the flag for recording to disk
' we can also play the track from memory
SetAudio Audio ' publish to dll
Task(%Demo_RecPlay).freq = 1000!/(Task(%Demo_Recplay).duur - 10)
jumpval = %True
EXIT SUB
END SELECT
CASE %True
' wait until the recording is done...
IF TrackStatus.Recording(tracknr) THEN
Task(%Demo_RecPlay).freq = 20
EXIT SUB
END IF
IF Audio.ToDisk THEN
' This playback will only work if saving is switched on.
CheckAudio Audio, App
Tracknr = PlayWaveFile ("GMT_" + HEX$(Audio.iCnt-1) + ".WAV" + CHR$(0), %Null)
IF Tracknr < 0 THEN EXIT SUB
Jumpval = 2
Task(%Demo_RecPlay).freq = 1000!/(Task(%Demo_RecPlay).duur - 10)
EXIT SUB
ELSE
retval = PlayAudioTrack (TrackNr, 0)
' if called as a function the return value should equal TrackNr
IF retval = TrackNr THEN
Jumpval = 2
Task(%Demo_RecPlay).freq = 1000!/(Task(%Demo_RecPlay).duur -10)
EXIT SUB
ELSEIF retval = -2 THEN
StopTask %Demo_RecPlay ' error
ELSE
Jumpval = %True
Task(%Demo_RecPlay).freq = 20
EXIT SUB
END IF
END IF
CASE 2
' wait until playback is done:
' CheckAudio Audio, App
Task(%Demo_RecPlay).freq = 20
IF TrackStatus.Playing(tracknr) THEN EXIT SUB
Jumpval = %False
END SELECT
END SUB

Filedate: 990301/2007-01-20


<Index > <Introduction> <General Functions>
<Fuzzy Functions> <Analysis Functions> <Acoustical Functions>
<Visualisation Functions> <File Management> <Spectral Functions>
To homepage dr.Godfried-Willem RAES