TDKDSPLIB 1.00

 

Written and ©2004, Thaddy de Koning

mailto:thaddy[at]thaddy.com

 

This library is copyrighted freeware.

         

Please give credits if you use it or part of it in your code

If you use this in commercial programs, please send me at least a copy to evaluate.

 

          No warranty whatsoever about usability or applicability concerning this code for any purpose is given.

          Use this code at your own risk.

          Only Dutch law is applicable.

          Dutch law understands the "whatsoever" part. No means No.

          If you do not agree, don't use it or contact me.

 

 

Introduction

 

This is a small library with routines to do audio bit rate conversion and clipping in Delphi 6 -7 and is completely written in Delphi’s built in assembler.

It does not depend on any other units. It also does not use any operating system specific code. It should therefore be fully compatible with BCB6+ and Kylix too, but this is not tested. If you try it with one of them, please let me know if it works.

 

I first started this library to do fast single-sample conversions, but when I thought about it, it seemed a lot more efficient to do the conversions in a buffer.

I couldn’t stop counting the

 

    For  I := 0 to SampleCount -1 do

        CallSomeFunctionThatJustDoesOneSampleAtaTimePushingAndPoppingIntoAndOutOfStackFramesUselessly;

 

(Example available on request)

 

in my code. So, buffered handling could potentially save a lot of overhead, since you have only at the most one stack frame per buffer.

On a typical buffer of 256 32 bit samples this saves 3 instructions per sample, that is 765 instructions too many. This may not sound a lot, but on simple routines that alone can take up to 20% of the processing because this is just a procedure’s internal cost. Externally, before the routine is called, there is also overhead, because parameters have to be moved to registers and or pushed on the stack. And again, that is times 256.

 

It proved to be very simple and fun to write this library. Frankly, I was amazed I couldn’t find anything similar, not even in the C (++) community.

As a general rule, these routines are not only written to be fast. They are also written to be small and concise. That means that fanatics may be able to optimize the code a lot –I seldom unroll loops for example-, but it also means that the code is very readable, even for people with just a hint of experience with inline assembler. And it still beats even highly optimized equivalent pure Delphi code hands down. Some routines take even less lines of code than the equivalent in Pascal would take.

 

I decided to focus on two main topics, for both of which I couldn’t find any usable free Delphi or other assembler source code on the internet:

 

Bit rate conversion

Clipping

 

I also added some handy off topic routines that just happened to need about the same basic code:

 

 

Note that all routines use the Delphi register calling convention.

Note that all routines assume LSB type, also known as Intel, byte order

Note that this code may still contain bugs, although it is thoroughly tested on both Intel and AMD machines.

Some code uses 3DNow and is only for AMD processors. I am not yet familiar with SSE but I will add that flavour in a future release.

 

If you find bugs or want additions to this library, please contact me per email at thaddy[at]thaddy.com

 

A warning should be given that the user has to be very careful to use the correct buffer sizes as indicated. No checks are done. The buffers need to be preferably a power of two, but most need at the least to be an even size. The routines will most likely crash if you do not obey these rules!

The programmer is always responsible to allocate the buffers in the correct sizes before calling any of these routines. Both the input and the output buffers need to be allocated. Again, no checks are done, be very, very careful!

 

 

Bit rate conversions

 

The bit rate buffer-conversion routines come in four flavours:

 

          Cvt<Input Type>To<Output Type>()                       : One in, One out

          Cvt<Input Type>To<Output Type>Inplace()           : One and the same in-out

          Cvt<Input Type>StereoTo<Output Type>Mono()   : One in, two out

          Cvt<Input Type>MonoTo<Output Type>Stereo()   : Two in, One out

 

They are for 8, 16 and 32 bit integer and 32 bit single precision floating point only, but I also added some 24 bit LSB per-sample converters.

The types are indicated as Int8, Int16, Int32 and 32f respectively.

The "samplecount" or “Sample” parameter is always relative to the sample size of the input buffer, again: in samples, not in bytes. As a general rule the sample count is relative to the leftmost parameter.

 

 

 

Integer 8 to XXX conversions

 

Procedure CvtInt8toInt16(Inbuffer:PshortintOutbuffer:PSmallInt; SampleCount: integer);

This converts 8 bit signed integer to 16 bit signed integer samples

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly twice the size in bytes of the input buffer

  

Procedure CvtInt8toInt32(Inbuffer:PshortintOutbuffer:PInteger; SampleCount: integer);

This converts 8 bit signed integers to 32 bit signed integer samples

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly four times the size in bytes of the input buffer

 

Procedure CvtInt8to32f(Inbuffer:PShortint; Outbuffer:Psingle; SampleCount: integer);

This converts 8 bit signed integers to 32 bit single precision floating point samples

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly four times the size in bytes of the input buffer

 

Procedure CvtInt8MonotoInt8Stereo(InLeft,InRight:Pshortint;Outbuffer:PSHortint; SampleCount: integer); 

Mixes two 8 bit mono channels to 8 bit stereo

 

Integer 16 to XXX conversions

 

Procedure CvtInt16toInt8(Inbuffer:PSmallIntOutbuffer:PShortInt; SampleCount: integer);

This converts 16 bit signed integers to 8 bit signed integer samples

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly half the size in bytes of the input buffer

 

Procedure CvtInt16to32f(Inbuffer:Psmallint; Outbuffer:Psingle; SampleCount: integer);

This converts 16 bit signed integers to 32 bit single precision floating point samples

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly half the size in bytes of the input buffer

 

Procedure CvtInt16to32fInPlace(buffer: Pointer;SampleCount: integer);

This expands a half full 16 bit integer buffer in place to a full 32bit singles buffer

The buffer should be exactly twice the size in bytes as the input!

This is a tiny bit slower, but saves on memory moves and buffer allocations.

Use it like this:

  

Procedure CvtInt16toInt32(Inbuffer:Psmallint;Outbuffer:PInteger; SampleCount: integer);

This converts a 16 bit signed integer buffer to 32 bit signed integers.

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly twice the size in bytes of the input buffer

 

Procedure CvtInt16StereoToInt16Mono(Inbuffer:Psmallint; OutLeft,OutRight:PSmallInt; SampleCount: integer);

This converts a 16 bit signed integer stereo buffer to two 16bit signed integer mono buffers.

The output buffers each need to be exactly half the size in bytes of the input buffer

 

Procedure CvtInt16StereoToInt32Mono(Inbuffer:Psmallint;OutLeft,OutRight:PInteger; SampleCount: integer);

This converts a 16bit signed integer stereo buffer to two 32bit signed integer  mono buffers

The output buffers each need to be exactly the same size in bytes of the input buffer

 

Procedure CvtInt16StereoTo32fMono(Inbuffer:Psmallint;OutbufferLeft: Psingle;OutbufferRight:PSingle; SampleCount: integer);

This converts a stereo 16 bit signed integer  input buffer to two floating point mono channels

Input is a stereo buffer, output two 32 bit single buffers, SampleCount equals the total number of input samples left + right

 

Procedure CvtInt16MonoTo32fStereo(InLeft,InRight:Psmallint; Outbuffer:PSingle; SampleCount: integer);

This creates a 32 bit single stereo buffer from two 16 bit signed  integer mono channels. Samplecount refers to the size of one mono buffer. The output buffer needs to be four times that size.

 

Procedure CvtInt16StereoTo32fMakeMono(Inbuffer:Psmallint; Outbuffer:Psingle; SampleCount: integer);

This creates a 32 bit floating point single mono channel from a 16 bit integer stereo buffer.

The buffers should be exactly the same size

 

Procedure CvtInt16MonoToInt16Stereo(InLeft,InRight:Psmallint; Outbuffer:PSmallInt;SampleCount: integer);

Mixes two 16 bit mono files to a 16 bit stereo buffer

 

Integer 32 to XXX conversions

 

Procedure CvtInt32toInt8(Inbuffer:PIntegerOutbuffer:PShortInt; SampleCount: integer);

This converts a 32 bit signed integer buffer to 8 bit signed integer

The output buffer is a fourth the size of the input buffer.

It works on both interleaved and non interleaved buffers

 

Procedure CvtInt32toInt16(Inbuffer:PIntegerOutbuffer:PSmallInt; SampleCount: integer);

This converts a 32 bit signed integer buffer to 16 bit signed integer

The output buffer is half the size of the input buffer

It works on both interleaved and non interleaved buffers

 

Procedure CvtInt32To32f(Inbuffer,Outbuffer: PInteger;SampleCount: integer);

This converts a 32 bit signed integer stereo buffer to 32 bit single precision floating point.

 

Procedure CvtInt32to32fInplace(buffer: PInteger; SampleCount: integer);

This converts a 32 bit signed integer stereo buffer to 32 bit single precision floating point in place,

 

Procedure CvtInt32to32fInplace3DNow(buffer: PInteger; SampleCount: integer);

This does the same as the last one, but uses AMD 3DNow!

The AMD routines need multiples of 32 bytes, since I unroll the loop 8 times in 4 mmx registers. I do not know of any ASIO buffers that are (buffer size mod 32) <> 0, but be warned! What you get back is raw speed!

 

Procedure CvtInt32StereoTo32fMakeMono(Inbuffer,Outbuffer: PInteger;SampleCount: integer);

This converts a 32bit stereo buffer to 32 singles and sums them result to mono before storing

The output buffer is half the size of the input buffer

 

Procedure CvtInt32StereoToInt16Mono(Inbuffer:PInteger; OutLeft,OutRight:PSmallInt; SampleCount: integer);

This converts a 32 bit signed integer buffer to 16 bit signed integer

The output buffers are a fourth the size of the input buffers

 

Procedure CvtInt32StereoToInt32Mono(Inbuffer:PIntegerOutLeft,OutRight:Pinteger; SampleCount: integer);

This converts a 32 bit signed integer stereo buffer to 32 bit signed integer mono.

The output buffers are half the size of the input buffer.

 

Procedure CvtInt32StereoTo32fMono(Inbuffer:PInteger;OutLeft,OutRight:PSingle; SampleCount: integer);

This converts a 32 bit signed integer stereo buffer to 32 bit single precision floating point mono buffers.

The output buffers are half the size of the input buffer.

 

Procedure CvtInt32MonoTo32fStereo(InLeft,InRight:Pinteger; Outbuffer:PSingle; SampleCount: integer);

This routine creates a 32 bit single precision floating point stereo buffer from two 32 bit signed integer mono channels.

Samplecount” refers to the size of one mono buffer.

The output buffer needs to be two times that size!

 

Procedure CvtInt32StereoTo32fMono(InBuffer:pInteger; OutLeft,OutRight:PSingle;samples:integer);

This converts a 32 bit signed integer stereo buffer to two single precision floating point buffers

The output buffers are half the size of the input buffer.

 

 

 

32 bit single precision floating point to XXX conversions

 

Procedure Cvt32fToInt16(Inbuffer: PsingleOutbuffer: Psmallint; SampleCount: integer);

This converts a 32 bit single precision floating point buffer to 16 bit signed integers, ASIOSTInt16LSB

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly half the size in bytes of the input buffer.

 

Procedure Cvt32fToInt16Dithered(InBuffer:Psingle;OutBuffer:PSmallInt;Samples:integer);

This procedure converts 32 bit single precision floating points to 16bit integers and applies a simple and fast triangular dither to reduce the noise floor.

It works for both interleaved and non interleaved buffers.

The output buffer needs to be exactly half the size in bytes of the input buffer.

It is a good idea to call ClipBuffer16 after you have called this procedure.

Normally you would call this procedure at the end of the audio chain, before you write a 16 bit mono wave file to disk.

It improves the audio quality compared to un-dithered material, but it is slower.

 

Procedure Cvt32fStereoToInt16MonoDithered(InBuffer:Psingle;OutBuffer:PSmallInt;Samples:integer);

This procedure converts 32 bit single precision floating points to two 16bit integer mono channels and applies a simple and fast triangular dither to reduce the noise floor.

It works for both interleaved and non interleaved buffers.

The outputs buffer needs to be exactly a fourth of the size in bytes of the input buffer.

Normally you would call this procedure at the end of the audio chain, before you write a 16 bit stereo wave file to disk.

It greatly improves the audio quality compared to un-dithered material, but it is definitely slower.

 

Procedure Cvt32fStereoToInt16MonoClipDithered(InBuffer:Psingle;OutLeft,OutRight:PSmallInt;Samples:integer);

This procedure converts 32 bit single precision floating points to two 16bit integer mono channels and applies a simple and fast triangular dither to reduce the noise floor. It then clips the signal to 32767 – 1/32768.

It works for both interleaved and non interleaved buffers.

The outputs buffer needs to be exactly a fourth of the size in bytes of the input buffer.

Normally you would call this procedure at the end of the audio chain, before you write a 16 bit wave file to disk.

It greatly improves the audio quality compared to un-dithered material, but it is definitely slower.

 

Note: Does anyone really needs and 8 bit blockdither? Can do, but I think it’s a bit  pointless right now.

 

Procedure Cvt32fStereoToInt16Mono(Inbuffer: PsingleOutLeft,OutRight: Psmallint; SampleCount: integer);

This converts a 32 bit single precision floating point stereo buffer to two 16 bit  signed integer mono buffers, ASIOSTInt16LSB

The output buffers need to be exactly one fourth the size in bytes of the input buffer.

 

Procedure Cvt32fStereoToMono(InBuffer,OutLeft,OutRight:Psingle;  samples:integer);

This converts a 32 bit single precision floating point buffer to two mono buffers.

The output buffers are exactly half the size of the input buffer.

 

Procedure Cvt32fMonoToStereo(InBuffer,OutLeft,OutRight:Psingle;  samples:integer);

This converts two 32 bit single precision floating point buffer into one stereo buffer.

The output buffer is exactly twice the size of one input buffer.

  

Procedure Cvt32fStereoToInt32Mono(InBuffer:pSingle; OutLeft,OutRight:PInteger;samples:integer);

This converts a 32 bit single precision floating point buffer to two 32 bit signed integer buffers.

The output buffers are half the size of the input buffer.

 

Procedure Cvt32fToInt32(InBuffer,OutBuffer:Pointer;samples:integer); 

This converts a 32 bit single precision floating point buffer to 32 a bit signed integer buffer.

Some 24 bit cards use this format for their output buffers too,

It works for both interleaved and non interleaved buffers.

 

Procedure Cvt32fToInt323DNow(Inbuffer,OutBuffer: PInteger;

                            SampleCount: integer);

This converts a 32 bit single precision floating point buffer to 32 a bit signed integer buffer using AMD 3DNow.

Some 24 bit cards use this format for their output buffers too,

It works for both interleaved and non interleaved buffers.

 

Procedure Cvt32fToInt32InPlace(Buffer:Pointer;samples:integer);

This converts a 32 bit single precision floating point buffer to 32 bit signed integer in place.

Some 24 bit cards use this format for their output buffers too,

It works for both interleaved and non interleaved buffers.

  

Procedure Cvt32fToInt32Inplace3DNow(buffer: PInteger; SampleCount: integer);

This does the same as the previous one, but uses AMD 3DNow!

The AMD routines need multiples of 32 bytes, since I unroll the

loop 8 times into 4 mmx registers. I do not know of any ASIO buffers

that are  BufSize mod 32 <> 0, but you have been warned!

What you get back is raw speed!

  

Function Cvt32fToInt32(value:single):integer;overload;

This does the same as the like-named buffer procedure, but on a single sample

 

Function Cvt32fToInt16(value:single):SmallInt;overload;

This does the same as the like-named buffer procedure, but on a single sample

 

Procedure CvtInt32MonoToInt32Stereo(InLeft,InRight:pInteger;OutBuffer:PInteger;samples:integer); 

Mixes two 32 bit integer mono channels to a 32 bit integer stereo file

(Can also be used for floats)

 

 

Buffer clipping

 

Note: if you are processing singles, it is often enough to clip just once at the end of the audio chain, unless you are sure your processing absolutely positively requires ranges -1...1.

I did not overload these functions, because you possibly might want to use un-typed buffer pointers.

 

Procedure ClipBuffer32f(Buffer:Psingle; samples:integer);

This procedure  takes a buffer of 32 bit single precision floating point samples and hard clips it to -1..1 range.

 

Procedure ClipBuffer32fDN(Buffer:Psingle;samples:integer):single;

This procedure implements a different algorithm that has a fortunate de-normalizing side effect.

It may reduce accuracy for small numbers. I.e. if you clip to [-1; 1], fractional part of the result will be quantized to 23 bits (or more, depending on the bit depth of the temporary results). Thus, 1e-20 will be rounded to 0. This has the side effect of de-normal number elimination.

The first clipping function is best used at the end of the audio chain.

The second one is best used to de-normalize a buffer before de-normal sensitive processing.

If you read this correctly, you’ll notice it actually performs two different clips, one on the min and max values and one on very small values around 0!

Therefore this may be more efficient for some tasks than the other hard-clipping procedure combined with separate de-normal elimination code.

 

Procedure ClipBuffer32fAtLimit(Buffer:Psingle; Value:single; samples:integer);

This is a simple limiter procedure. The value parameter should be in the range of 0…1.

Do not confuse this with Volume control. It hard-clips all samples that are above the value or below the negated value.

Of course it’s faster than the volume procedures. See also AdjustVolume32fAndClipDN

 

The next clipping functions do not work on older Pentiums! They need a Pentium Pro, AMD Duron or better CPU.

I do not think this is really an issue, because intensive real time floating point audio processing requires a better specification than a Pentium 1 anyway.

 

Procedure ClipBuffer32(Buffer:PInteger; samples:integer);

Takes a buffer of 32 bit signed integers and hard clips between $7FFFFFFF and $80000000

 

 Procedure ClipBuffer24(Buffer:PInteger; samples:integer);

Takes a buffer of 32 bit signed integers and hard clips to 24 bit range, $7FFFFF, $800000

 

 Procedure ClipBuffer16(Buffer:Psmallint; samples:integer);

Takes a buffer of 16 bit signed integers and hard clips between $7FFF and $8000

 

Procedure ClipBuffer8(Buffer:Pshortint; samples:integer);

Takes a buffer of 8 bit signed integers and hard clips between $7F and $80

 

 

Volume control

 

Procedure AdjustVolume32f(Buffer:PSingle;Volume:single; samples:integer);

This adjusts the volume on a 32 bit single buffer.

It works for both interleaved and non interleaved buffers.

Volume values should be in the range of 0...1, unless you want to amplify very soft material

Warning: Any value is accepted!

 

Procedure AdjustVolume32fDN(Buffer:Psingle;Volume:single; samples:integer);

This does the same as the previous one, but inlined checking/repairing de-normal values on the fly.

 

Procedure AdjustVolume32fAndClipDN (Buffer:Psingle;Volume:single;samples:integer);

This procedure adjusts the volume and clips it both on min and max values as on very small de-normal values around zero.

This is very useful for gain control, since it keeps volume at workable limits under all circumstances, both very loud and very soft.

It works by first adjusting the volume to the requested value and then clipping it to -1…1 using the ClipBuffer32fDN algorithm.

 

 Procedure AdjustVolume32fLeft(Buffer:PSingle;Volume:single; samples:integer);

This adjusts the volume from buffer start, skipping every other sample, for separate treatment on interleaved buffers.

Volume values should be 0...1, unless you want to amplify very soft material

Warning: Any value is accepted!

 

Procedure AdjustVolume32fLeftDN(Buffer:Psingle;Volume:single; samples:integer);

The same, but with inline checking/repairing de-normal values on the fly

 

Procedure AdjustVolume32fRight(Buffer:PSingle;Volume:single; samples:integer);

This adjusts the volume from buffer start + 1 sample, skipping every other sample, for separate treatment on stereo buffers.

Volume values should be 0...1, unless you want to amplify very soft material

Warning: Any value is accepted!

 

Procedure AdjustVolume32fRightDN(Buffer:Psingle;Volume:single; samples:integer);

The same but with inline checking/repairing de-normal values on the fly

 

Function SoftestSample32f(Inbuffer: Psingle;SampleCount: integer):single; 

This function traces a buffer for the softest sample.

This is mainly useful as a development function to evaluate signal levels, but is also useful in off-line audio processing or look-ahead on smaller buffers.

It is perfectly acceptable to use it real-time with the ASIO buffers of a good quality audio card.

It returns the absolute value of the softest signal in the buffer, a positive range nearing to zero.

 

Function LoudestSample32f(Inbuffer: Psingle;SampleCount: integer):single;

This function traces a buffer for the loudest sample.

This is mainly a development utility to evaluate signal levels, but you can also use it for off-line audio processing or look ahead on smaller buffers.

It is perfectly acceptable to use it real-time with the ASIO buffers of a good quality audio card.

It returns the absolute value of the loudest signal in the buffer, so it’s in the range of 0…1

 

 

24 bit integer single sample manipulation

 

Function Cvt24BitTo32(Sample : T24BitSample) : integer;

This function converts a single 24bit lsb sample to a 32 bit sample

 

Function Cvt32BitTo24(Sample : integer) : T24BitSample;

This function converts a 32bit integer sample to a 24 bit lsb sample

 

Function Cvt32fTo24LSB(Sample : single) : T24BitSample;

This function converts a 32 bit single precision floating point sample to a 24 bit lsb sample

 

 

Phase handling and voice cancelling

 

Procedure InvertPhase32fMono(Inbuffer: Psingle;Outbuffer: PSingle; SampleCount: integer);

This procedure inverts the phase of all the samples in the inputbuffer

 

Procedure InvertPhase32fMonoInplace(buffer: Psingle;SampleCount: integer);

This procedure inverts the phase of all the samples in the buffer in place.

 

Procedure InvertPhase32fStereo(Inbuffer: Psingle;Outbuffer: PSingle; SampleCount: integer);

This procedure inverts the phase of the right channel in a stereo buffer

 

Procedure InvertPhase32fStereoInplace(buffer: PSingle; SampleCount: integer);

This procedure inverts the phase of the right channel of a stereo buffer in place.

 

Procedure VoiceCancel32f(Inbuffer: Psingle;OutBuffer:Psingle;SampleCount: integer);

This procedure inverts the phase of one of the stereo channels, and then mixes the stereo signal to mono.

This has the effect of eliminating the centre of the audio and thus it is sometimes inaccurately called “Voice Cancellation” since the singer is often mixed in the centre. Note that for best results you should combine it with something like a >12dB/Oct low pass filter on a copy of the input signal at 200 ~ 300Hz before you do the cancelling and add the signals together after processing. Otherwise you may also loose the bass frequencies which tend to take up much of the middle of the spectrum as well. You may further enhance the result by feeding it through a 3D sound processor first. This basically changes the phase of parts of the signal to obtain a roomy illusion and can improve the accuracy of the voice removal, since it influences the stereo spread. See below, use them in series.

The output buffer is half the size of the input buffer.

 

Procedure TwoChannelVoiceCancel32f(Inbuffer: Psingle;OutBuffer:Psingle;SampleCount: integer);

This procedure inverts the phase of one of the two stereo channels and mixes them down to mono.

It then outputs both mono channels as an interleaved buffer, thus ensuring that the output buffer is the same length as the input buffer.

 

Procedure Sound3D32f(Buffer:Psingle,Volume:Single, Samplecount:Integer);

This procedure creates the well known three-dimensional sound effect by adding a small amount of the average of the left and right channels to the left and right samples, thus creating a spatial effect. Values below 0.1 have the effect of narrowing the stereo image. Recommended values are between 0 and 1 or a bit higher and must be positive. I have included it here, because it is a really a phase effect. Note that the DC-DSP library for Delphi by Milenko Mitrovic contains a component that uses the same algorithm and has optimizations for AMD 3DNow and SSE.

 

 

Utilities

 

Function FastEnsureRange(const Test, Min,Max: Integer) : Integer;overload;

Function FastEnsureRange(const Test, Min, max:single):single;overload;

Function FastEnsureRangeDN(const Test, Min, max:single):single;overload;

 

These are fast RTL EnsureRange replacement functions. The first two need a Pentium Pro, AMD Duron or better.

The last one is based on an algorithm by Laurent de Soras of Ohmforce fame: It may reduce accuracy for small numbers. I.e. if you clip to [-1; 1], the fractional part of the result will be quantized to 23 bits, or more, depending on the bit depth of the temporary results. Thus, 1e-20 will be rounded to 0. This has the fortunate side effect of de-normal number elimination.

If you read this correctly, it actually performs two different range checks, one on the min and max values and one on very small values around 0!

Therefore this may be more efficient for some tasks than the other range procedure.

 

Procedure SwapChannels32 (Buffer:Pointer;samples:integer);

Swaps right and left channel for any 32bit type, both 32 bit Integer and 32 bit single precision floating point.

 

Procedure SwapChannels16 (Buffer:PsmallInt;samples:integer);

Swaps right and left channel for 16 bit

 

Procedure SwapChannels8 (Buffer:PShortInt;samples:integer); 

Swaps right and left channel for 8 bit integers

 

Function Undenormalize(fValue:single):single;assembler;

A simple un-de-normalize function, based on a widely used C inline macro

 

 

 

Recommended resources 

Here are some very useful resources regarding programming Audio with Delphi:

 

The website of Milenko Mitrovic contains discussions about using his DC-DSP lib and you can download his brilliant DC_DSP library there.

Its focus is more on DirectX than on generic audio programming, but the components are very good and do not rely on DirectX.

(Important to me, since I almost only use ASIO)

http://dsp-worx.de

 

TobyBear’s website contains a lot of example code for writing VST plug-in and hosts and you can download his very good VST plug-in template library, a VST host component that is now way better than my own and many other freebies there. He also has very extensive links pages to whatever dsp resource you may ever need. He also has some of the most original shareware plug-ins on the web (and has a knack for quirky coloured user interface designs).

http://www.tobybear.de

 

Frederic VanMol’s website contains his original translations of both the Steinberg ASIO SDK and the VST SDK.

http://www.axiworld.be

 

The musicdsp.org website contains a lot of information, algorithms and a very good pdf file full of almost ready to use dsp stuff. Most of the source code is in C or C++, but the algorithms are pretty well explained. Not much Delphi stuff yet.

http://www.musicdsp.org

 

The KOL website holds most of my sources and examples, as well as lots of other audio related stuff and lots more freeware sources to write very small applications with Vladimir Kladov’s brilliant KOL VCL replacement library. Check it out, it’s brilliant! For years I use nothing else for my home programming and only use the VCL or CLX for commercial work. Using KOL your native code 32 bit Windows applications are about a tenth the size of the VCL equivalent. That makes them compare favourably to JAVA appletsJ for distributions on the web. The KOL framework is almost entirely written in BASM, but you don’t have to bother about that: all classes -actually they are objects- have an exact equivalent in pure Delphi if you would choose to and it is completely transparent to the programmer. It also supports Freepascal for Windows and work for Kylix and Freepascal under Linux is coming along nicely.

http://www.xcl.cjb.net

http://bonanzas.rinet.ru

 

Not audio related, but of interest to pascal and Delphi fans should be the Freepascal Delphi compatible cross-platform compiler, that has become truly amazingly good in the newest versions. It beats Borland’s products hands down in cross-platform compatibity, although its development environment is not yet as productive.

http://www.freepascal.org

 

Did you know one of the best audio programs ever was written in Delphi? It’s Fruityloops, now known as FL Studio.

 

There are really not many more really good resources, which is a bit sour. But check out the Linux community for lots of audio related material in C and C++. It is often very good and very translatable.

 

 

Conclusion

Well, my previous really comprehensive and topical inline assembler library was the TDKLIB GUI utility library for DOS which was of course 16 bits and for Turbo C, Turbo Pascal and Powerbasic and was released in 1989. It was distributed via pre-web era bulletin boards and had during its four year life-cycle a total of about 13.400 downloads. It reached version 4 in 1993.

After more than fourteen years it was time to do another one! I am pretty sure it can grow and improve over time. If you use it, please give me feedback to motivate me to do so. Additional code to include in this library is also appreciated. I will include it along with credits.

 

Have fun,

 

Thaddy