Thread View: borland.public.delphi.multimedia
1 messages
1 total messages
Started by Paul Nicholls
Wed, 18 Jun 2008 03:32
Direct Digital Synthesis class for audio
Author: Paul Nicholls
Date: Wed, 18 Jun 2008 03:32
Date: Wed, 18 Jun 2008 03:32
200 lines
8938 bytes
8938 bytes
Using information off the net about Direct Digital Synthesis
(http://www.analog.com/library/analogDialogue/archives/38-08/dds.html) as an
example, I have created a Direct Digital Synthesizer class (TDDS) which can
currently output square and sine waves (will upgrade to do triangle and
sawtooth as well later).
You can produce your own arbitrary waveform at the desired frequency and
sample rate on as well as the 4 built in wave types.
You would do this using your own TPhaseToAmplitude function 'event' to
generate your own custom output.
I hope you guys find it useful
//***** BEGINNING OF CODE *******
Unit direct_digital_synthensizer;
Interface
Type
{..............................................................................}
TDDS = Class;
TPhaseToAmplitude = Function(Const ADDS : TDDS) : Single;
TNumberOfBits = 2..31;
TWaveType = (wtSawtooth,wtSquare,wtTriangle,wtSine,wtCustom);
TDefinedWaveType = Low(TWaveType)..Pred(High(TWaveType));
TDDS = Class
Private
FOnPhaseToAmplitude : TPhaseToAmplitude;
FPhaseRegResolution : TNumberOfBits;
FPhaseRegMaxPlus1 : LongWord;
FPhaseRegMax : LongWord;
FPhaseRegHalfMax : LongWord;
FPhaseRegQuaterMax : LongWord;
FWaveType : TWaveType;
FSampleRate : LongWord;
FFrequency : Single;
FPhase : LongWord;
FPhaseReg : LongWord;
FPhaseRegIncrement : LongWord;
FAmplitude : Single;
Procedure FSetOnPhaseToAmplitude(Const AValue : TPhaseToAmplitude);
Procedure SetPhaseRegIncrement;
Public
Constructor Create(Const APhaseRegResolution : TNumberOfBits);
Procedure SetWaveType (Const AValue : TDefinedWaveType);
Procedure SetSampleRate(Const AValue : LongWord);
Procedure SetFrequency (Const AValue : Single);
Procedure Reset;
Procedure Synthesize;
Property PhaseRegResolution : TNumberOfBits Read
FPhaseRegResolution;
Property PhaseRegMaxPlus1 : LongWord Read
FPhaseRegMaxPlus1;
Property PhaseRegMax : LongWord Read FPhaseRegMax;
Property PhaseRegHalfMax : LongWord Read
FPhaseRegHalfMax;
Property PhaseRegQuaterMax : LongWord Read
FPhaseRegQuaterMax;
Property WaveType : TWaveType Read FWaveType;
Property SampeRate : LongWord Read FSampleRate;
Property Frequency : Single Read FFrequency;
Property Phase : LongWord Read FPhase;
Property Amplitude : Single Read FAmplitude;
Property OnPhaseToAmplitude : TPhaseToAmplitude Read
FOnPhaseToAmplitude
Write
FSetOnPhaseToAmplitude;
End;
{..............................................................................}
Implementation
{..............................................................................}
{..............................................................................}
Function PhaseToAmplitude_Sawtooth(Const ADDS : TDDS) : Single;
Begin
Result := 0;
End;
{..............................................................................}
{..............................................................................}
Function PhaseToAmplitude_Square(Const ADDS : TDDS) : Single;
Begin
If ADDS.Phase <= ADDS.PhaseRegHalfMax Then
Result := -1
Else
Result := +1;
End;
{..............................................................................}
{..............................................................................}
Function PhaseToAmplitude_Triangle(Const ADDS : TDDS) : Single;
Begin
Result := 0;
End;
{..............................................................................}
{..............................................................................}
Function PhaseToAmplitude_Sine(Const ADDS : TDDS) : Single;
Begin
Result := Sin(2 * PI * ADDS.Phase/ADDS.PhaseRegMaxPlus1);
End;
{..............................................................................}
{..............................................................................}
Constructor TDDS.Create(Const APhaseRegResolution : TNumberOfBits);
Begin
Inherited Create;
FOnPhaseToAmplitude := Nil;
FPhaseRegResolution := APhaseRegResolution;
FPhaseRegMaxPlus1 := LongWord((1 Shl FPhaseRegResolution));
FPhaseRegMax := LongWord((1 Shl FPhaseRegResolution) - 1);
FPhaseRegHalfMax := LongWord(FPhaseRegMaxPlus1 Shr 1);
FPhaseRegQuaterMax := LongWord(FPhaseRegMaxPlus1 Shr 2);
FSampleRate := 44100;
FFrequency := 100;
SetPhaseRegIncrement;
SetWaveType(wtSine);
Reset;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.FSetOnPhaseToAmplitude(Const AValue : TPhaseToAmplitude);
Begin
If Not Assigned(AValue) Then Exit;
FOnPhaseToAmplitude := AValue;
FWaveType := wtCustom;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.SetWaveType(Const AValue : TDefinedWaveType);
Begin
FWaveType := AValue;
Case FWaveType Of
wtSawtooth : FOnPhaseToAmplitude := PhaseToAmplitude_Sawtooth;
wtSquare : FOnPhaseToAmplitude := PhaseToAmplitude_Square;
wtTriangle : FOnPhaseToAmplitude := PhaseToAmplitude_Triangle;
wtSine : FOnPhaseToAmplitude := PhaseToAmplitude_Sine;
End;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.SetPhaseRegIncrement;
Begin
FPhaseRegIncrement := LongWord(Trunc(FPhaseRegMax * FFrequency /
FSampleRate)) And FPhaseRegMax;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.SetSampleRate(Const AValue : LongWord);
Begin
FSampleRate := AValue;
SetPhaseRegIncrement;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.SetFrequency(Const AValue : Single);
Begin
FFrequency := AValue;
SetPhaseRegIncrement;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.Reset;
Begin
FPhase := 0;
FPhaseReg := 0;
End;
{..............................................................................}
{..............................................................................}
Procedure TDDS.Synthesize;
Begin
FPhase := FPhaseReg;
FAmplitude := FOnPhaseToAmplitude(Self);
{$R-}
FPhaseReg := LongWord(FPhaseReg + FPhaseRegIncrement) And FPhaseRegMax;
{$R+}
End;
{..............................................................................}
{..............................................................................}
End.
//***** END OF CODE *******
You set up the desired parameters in the class, call the Reset method once,
and each time you need a sample, just call the Synthesize method to generate
a value you can then read using the Amplitude or Phase properties.
cheers,
Paul
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads