Page 3 of 3 FirstFirst 123
Results 21 to 24 of 24

Thread: tone generation in .WAV format using Pascal

  1. #21

    tone generation in .WAV format using Pascal

    Quote Originally Posted by chronozphere
    As far as i can tell, you do not need an array to store the tone frequencies. They can be calculated using some formula (You have to search wikipedia, I'm sure it will be there somewhere )
    Sorry, I'm not sure what you are talking about.

    I'm not storing tone frequencies in any array...

    EDIT: Unless you mean my TDDS class in one of my earlier posts?

    That is using an array to store tones that are calculated only once so it is faster, and also I can use custom waveforms that are much more complex than the simple Sine, Square, Triangle, Sawtooth waveforms.

    I have got an updated version of that now too if you are interested, as well as a TWavetable class which holds TWaveform classes (individual custom waveforms; as simple or complex as you want).

    cheers,
    Paul

  2. #22

    tone generation in .WAV format using Pascal

    That is using an array to store tones that are calculated only once so it is faster, and also I can use custom waveforms that are much more complex than the simple Sine, Square, Triangle, Sawtooth waveforms.
    Okay.. That makes sense.

    Edit: You might want to pre-calculate this data instead of copying it from anothe resource. Then you will be able to generate a bigger array (more octaves) and you will have more precise data. Check out the "Tone frequencie" section on this wiki-page:

    http://en.wikipedia.org/wiki/Note

    This looks very cool.. Audio has always been like a second hobby of mine, and i often tried to find audio-programming resources. Thanks for sharing these sources.
    Coders rule nr 1: Face ur bugz.. dont cage them with code, kill'em with ur cursor.

  3. #23

    tone generation in .WAV format using Pascal

    Hi chronozphere,

    I'm glad I could help :-)

    BTW, when you asked about me storing tones in arrays, did you mean the note frequencies themselves?

    If so, then yes I am doing that...I have an array I filled with my calculated versions of the notes that I can then lookup using constants.

    I have 12 notes (0 - 11) in each of 9 (0 - octaves...

    I used the note formula mentioned in a similar page to the one you posted.

    I now have a TOscillator class (uses the TDDS class internally) for producing sine, cosine, triangle, sawtooth, square, and noise waveforms at the desired frequency. Also can use the TWaveform class I told you abotu for custom waveforms.

    I also have a TEnvelope class to shape the output volume of the oscillator, and a TMixer class that can mix multiple outputs into one output.

    Let me know if you are interested in these too

    cheers,
    Paul

  4. #24

    Re: tone generation in .WAV format using Pascal

    Hi all,
    I'm re-posting my TWAVBuffer class code as the previous time I posted it, the output code was garbled, and I also want to test the new formatter

    [pascal]
    Unit wav_buffer;
    {$IFDEF fpc}
    {$MODE DELPHI}
    {$ENDIF}
    {$H+}
    Interface

    Uses
    Classes;

    Type
    {................................................. .............................}
    TWAVBuffer = Class
    Private
    FStream : TStream;
    FDuration_mSec : LongWord;
    FNumberOfChannels : Byte;
    FBitsPerSample : Byte;
    FSampleRate : LongWord;
    FNumberOfSamples : LongWord;
    FDataSize : LongWord;
    Procedure WriteWAVHeader;
    Public
    Constructor Create(Const AStream : TStream;
    Const ADuration_mSec : LongWord;
    Const ANumberOfChannels : Byte;
    Const ABitsPerSample : Byte;
    Const ASampleRate : LongWord);
    Procedure Reset;
    Procedure WriteSamples(Const ASamples : Array Of Single);
    Property NumberOfSamples : LongWord Read FNumberOfSamples;
    End;
    {................................................. .............................}

    Implementation

    {................................................. .............................}

    {................................................. .............................}
    Constructor TWAVBuffer.Create(Const AStream : TStream;
    Const ADuration_mSec : LongWord;
    Const ANumberOfChannels : Byte;
    Const ABitsPerSample : Byte;
    Const ASampleRate : LongWord);
    Begin
    FStream := AStream;
    FDuration_mSec := ADuration_mSec;
    FNumberOfChannels := ANumberOfChannels;
    FBitsPerSample := ABitsPerSample;
    FSampleRate := ASampleRate;
    If Not (FNumberOfChannels In[1,2]) Then FNumberOfChannels := 1;
    If Not (FBitsPerSample In[8,16]) Then FBitsPerSample := 8;
    FNumberOfSamples := (FDuration_mSec * FSampleRate) Div 1000;
    FDataSize := (FBitsPerSample Shr 3) * FNumberOfChannels * FNumberOfSamples;
    WriteWAVHeader;
    End;
    {................................................. .............................}

    {................................................. .............................}
    Procedure TWAVBuffer.WriteWAVHeader;
    Const
    WAVE_FORMAT_PCM = 1;
    RiffId : AnsiString = 'RIFF';
    WaveId : AnsiString = 'WAVE';
    FmtId : AnsiString = 'fmt ';
    DataId : AnsiString = 'data';

    Type
    TWaveHeader = Packed Record
    wFormatTag : Word; { format type }
    nChannels : Word; { number of channels (i.e. mono, stereo, etc.) }
    nSamplesPerSec : LongWord; { sample rate }
    nAvgBytesPerSec : LongWord; { for buffer estimation }
    nBlockAlign : Word; { block size of data }
    wBitsPerSample : Word; { number of bits per sample of mono data }
    cbSize : Word; { the count in bytes of the size of }
    End;
    Var
    WaveHeader : TWaveHeader;
    RiffCount : Integer;
    TempInt : LongWord;
    Begin
    With WaveHeader Do
    Begin
    wFormatTag := WAVE_FORMAT_PCM;
    nChannels := FNumberOfChannels;
    nSamplesPerSec := FSampleRate;
    wBitsPerSample := FBitsPerSample;
    nBlockAlign := nChannels * wBitsPerSample Shr 3;
    nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
    cbSize := 0;
    End;
    {Calculate length of sound data and of file data}
    RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(LongWord) +
    SizeOf(TWaveHeader) + Length(DataId) + SizeOf(LongWord) + FDataSize; // file data
    {write out the wave header}
    FStream.Write(RiffId[1] , 4); // 'RIFF'
    FStream.Write(RiffCount , SizeOf(LongWord)); // file data size
    FStream.Write(WaveId[1] , Length(WaveId)); // 'WAVE'
    FStream.Write(FmtId[1] , Length(FmtId)); // 'fmt '
    TempInt := SizeOf(TWaveHeader);
    FStream.Write(TempInt , SizeOf(LongWord)); // TWaveFormat data size
    FStream.Write(WaveHeader , SizeOf(WaveHeader)); // WaveFormatEx record
    FStream.Write(DataId[1] , Length(DataId)); // 'data'
    FStream.Write(FDataSize , SizeOf(LongWord)); // sound data size
    End;
    {................................................. .............................}

    {................................................. .............................}
    Procedure TWAVBuffer.Reset;
    Begin
    FStream.Seek(0,soFromBeginning);
    WriteWAVHeader;
    End;
    {................................................. .............................}

    {................................................. .............................}
    Procedure TWAVBuffer.WriteSamples(Const ASamples : Array Of Single);
    Var
    Sample_8Bit : Byte;
    Sample_16Bit : SmallInt;
    Sample : Single;
    i : Integer;
    Begin
    For i := 0 To High(ASamples) Do
    Begin
    Sample := ASamples[i];
    // clip sample to between [-1,+1]
    If Sample < -1.0 Then Sample := -1.0
    Else If Sample > +1.0 Then Sample := +1.0;
    // write sample to stream
    If FBitsPerSample = 8 Then
    Begin
    Sample_8Bit := 127 + Trunc(127 * Sample);
    FStream.Write(Sample_8Bit,SizeOf(Sample_8Bit));
    End
    Else
    If FBitsPerSample = 16 Then
    Begin
    Sample_16Bit := Trunc(32767 * Sample);
    FStream.Write(Sample_16Bit,SizeOf(Sample_16Bit));
    End;
    End;
    End;
    {................................................. .............................}

    {................................................. .............................}
    End.
    [/pascal]

    cheers,
    Paul

Page 3 of 3 FirstFirst 123

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •