Results 1 to 5 of 5

Thread: Function Generator [Work In Progress]

  1. #1
    Constant Bitrate
    Join Date
    Mar 2008
    Posts
    162

    Function Generator [Work In Progress]

    So, here is the GIU for it so far.

    It will show the Frequency via numbers in the top box, and I hope to be able to pull off a very basic graphic of an oscilloscope in the bottom.

    I just wanted a cool way to play test tones, and have seen people use actual function generators to do so.

    I figured..hey..why not make a software version?





    Now I have to figure out how to get Visual basic to output a test tone.
    The quick and dirty way would be to simply have a sound file for each freq, but I am hoping to be able to produce the sound on the fly.

  2. #2
    Variable Bitrate Arrow's Avatar
    Join Date
    Feb 2006
    Location
    West Lafayette, IN
    Posts
    288
    You'll need some outside help to get VB to output a tone. As far as I know, it can't do it on it's own.

  3. #3
    Constant Bitrate
    Join Date
    Mar 2008
    Posts
    162
    It can do it by itself.

    It can either load the file up and play it, or it can calculate the sound and write it to file at run time.

    The latter requires knowledge of how a .wav file is composed on a byte level. So for now I will be using the first method. Version 2.0 will use the latter method once I have time to work it out.

  4. #4
    Maximum Bitrate CarComp's Avatar
    Join Date
    Oct 2001
    Location
    Indiana
    Posts
    515
    VB can most certainly play tones. Here is some code to generate a small wav file. Just use the Windows Media Player 6.4 control. That should be good enough. Just put the small wav file in a loop.
    Code:
    'Write sound data to wave files
    'By Axel Brink
    '21-May-2002
    'Write comments to axel@fmf.nl
    'You can use this file freely, at your own risk
    'Credits would be appreciated, but are not necessary
    'Please do not redistribute this source code without my name
    'Wavefile format information used from http://ccrma-www.stanford.edu/CCRMA/Courses/422:1998/projects/WaveFormat/
    'Some comments from this address are copied here (marked ##)
    '
    'Example use:
    '
    'Private Sub cmdHighQuality_Click()
    '  Const Hertz As Single = 2 * 3.14159265 / 44100 'use sin(sam*hertz) to get a tone of 1 hertz
    '  Dim DataBytes(0 To 1, 0 To 44099) As Long
    '  Dim sam As Long
    '  Dim chan As Integer
    '
    '  MousePointer = vbHourglass
    '  For sam = 0 To 44099
    '    For chan = 0 To 1
    '      DataBytes(0, sam) = 4000 * Sin(500 * sam * Hertz)
    '      DataBytes(1, sam) = 4000 * Sin(300 * sam * Hertz)
    '    Next chan
    '  Next sam
    '
    '  WriteWave txtOutputPath.Text, CreateWaveArray(DataBytes, 44100, 16)
    '  MousePointer = vbDefault
    'End Sub
    '
    'Private Sub cmdLowQuality_Click()
    '  Const Hertz As Single = 2 * 3.14159265 / 22050 'use sin(sam*hertz) to get a tone of 1 hertz
    '  Dim DataBytes(0 To 0, 0 To 22049) As Long
    '  Dim sam As Long
    '
    '  MousePointer = vbHourglass
    '  For sam = 0 To 22049
    '    DataBytes(0, sam) = 127 + 40 * Sin(800 * sam * Hertz) + 40 * Sin(300 * sam * Hertz)
    '  Next sam
    '
    '  WriteWave txtOutputPath.Text, CreateWaveArray(DataBytes, 22050, 8)
    '  MousePointer = vbDefault
    'End Sub
    
    
    Option Explicit
    Public Const WAVE_MIN = -32768 'Extreme sample values for 16-bit samples
    Public Const WAVE_MAX = 32767
      
    
    Public Function CreateWaveArray(WaveData() As Long, SampleRate As Long, BitsPerSample As Long) As Byte()
    'Reads sample data and returns an array with bytes which can be
    'written to a .wav file
    'Uses PCM (i.e. no compression)
    
    'WaveData:  * Contents:  Sample values of type Long
    '           * Structure: An array(channel, samplenumber)
    '           * Channels:  The number of elements in the first dimension
    '                        determines the number of channels
    '           * Samples:   The number of elements in the second dimension
    '                        determines the number of samples
    '                        8-bit samples must be between 0 and 255
    '                        16-bit samples must be between -32768 and 32767
    '           Note that indexing is supposed to start at 0.
    'SampleRate:             Number of samples per second. Typically 44100.
    'BitsPerSample:          Number of bits per sample. 8 or 16.
    
      Const Byte1Mask As Long = 255      'Long integers are stored little endian.
      Const Byte2Mask As Long = 65280    'These bit masks select bytes from a number to store.
      Const Byte3Mask As Long = 16711680
      Const Byte2Divisor As Long = 256
      Const Byte3Divisor As Long = 65536
      Const Byte4Divisor As Long = 16777216
      
      Dim NumSamples As Long
      Dim NumChannels As Long
      Dim FileSize As Long
      Dim ByteRate As Long
      Dim BlockAlign As Long '## "The number of bytes for one sample including all channels.
                             '    I wonder what happens when this number isn't an integer?"
      Dim OutputFile() As Byte
      Dim ChunkSize As Long  '## "36 + SubChunk2Size, or more precisely:
    '                               4 + (8 + SubChunk1Size) + (8 + SubChunk2Size)
    '                               This is the size of the rest of the chunk
    '                               following this number.  This is the size of the
    '                               entire file in bytes minus 8 bytes for the
    '                               two fields not included in this count:
    '                               ChunkID and ChunkSize."
      Dim Subchunk2Size As Long '## "== NumSamples * NumChannels * BitsPerSample/8
    '                               This is the number of bytes in the data.
    '                               You can also think of this as the size
    '                               of the read of the subchunk following this
    '                               number."
      Dim SampleNr As Long
      Dim ChannelNr As Long
    
      If BitsPerSample <> 8 And BitsPerSample <> 16 Then Stop
    
      NumChannels = UBound(WaveData, 1) + 1
      NumSamples = UBound(WaveData, 2) + 1
    
      ByteRate = SampleRate * NumChannels * BitsPerSample / 8
      BlockAlign = NumChannels * BitsPerSample / 8
    
      FileSize = 44 + NumSamples * BlockAlign
      ChunkSize = FileSize - 8
      Subchunk2Size = NumSamples * NumChannels * BitsPerSample / 8
    
      ReDim OutputFile(0 To FileSize - 1) As Byte
      
      '** ChunkID **
      OutputFile(0) = Asc("R")
      OutputFile(1) = Asc("I")
      OutputFile(2) = Asc("F")
      OutputFile(3) = Asc("F")
      
      '** ChunkSize **
      OutputFile(4) = ChunkSize And Byte1Mask 'Little endian
      OutputFile(5) = (ChunkSize And Byte2Mask) \ Byte2Divisor
      OutputFile(6) = (ChunkSize And Byte3Mask) \ Byte3Divisor
      OutputFile(7) = ChunkSize \ Byte4Divisor
      
      '** Format **
      OutputFile(8) = Asc("W")
      OutputFile(9) = Asc("A")
      OutputFile(10) = Asc("V")
      OutputFile(11) = Asc("E")
      
      '** Subchunk1ID **
      OutputFile(12) = Asc("f")
      OutputFile(13) = Asc("m")
      OutputFile(14) = Asc("t")
      OutputFile(15) = Asc(" ")
      
      '** Subchunk1Size ** (16 for PCM)
      OutputFile(16) = 16 And Byte1Mask
      OutputFile(17) = (16 And Byte2Mask) \ Byte2Divisor
      OutputFile(18) = (16 And Byte3Mask) \ Byte3Divisor
      OutputFile(19) = 16 \ Byte4Divisor
      
      '** AudioFormat ** (1 for PCM)
      OutputFile(20) = 1 And Byte1Mask
      OutputFile(21) = (1 And Byte2Mask) \ Byte2Divisor
      
      '** NumChannels **
      OutputFile(22) = NumChannels And Byte1Mask
      OutputFile(23) = (NumChannels And Byte2Mask) \ Byte2Divisor
    
      '** SampleRate **
      OutputFile(24) = SampleRate And Byte1Mask
      OutputFile(25) = (SampleRate And Byte2Mask) \ Byte2Divisor
      OutputFile(26) = (SampleRate And Byte3Mask) \ Byte3Divisor
      OutputFile(27) = SampleRate \ Byte4Divisor
      
      '** ByteRate **
      OutputFile(28) = ByteRate And Byte1Mask
      OutputFile(29) = (ByteRate And Byte2Mask) \ Byte2Divisor
      OutputFile(30) = (ByteRate And Byte3Mask) \ Byte3Divisor
      OutputFile(31) = ByteRate \ Byte4Divisor
      
      '** BlockAlign **
      OutputFile(32) = BlockAlign And Byte1Mask
      OutputFile(33) = (BlockAlign And Byte2Mask) \ Byte2Divisor
      
      '** BitsPerSample **
      OutputFile(34) = BitsPerSample And Byte1Mask
      OutputFile(35) = (BitsPerSample And Byte2Mask) \ Byte2Divisor
      
      '** Subchunk2ID **
      OutputFile(36) = Asc("d")
      OutputFile(37) = Asc("a")
      OutputFile(38) = Asc("t")
      OutputFile(39) = Asc("a")
      
      '** Subchunk2Size **
      OutputFile(40) = Subchunk2Size And Byte1Mask
      OutputFile(41) = (Subchunk2Size And Byte2Mask) \ Byte2Divisor
      OutputFile(42) = (Subchunk2Size And Byte3Mask) \ Byte3Divisor
      OutputFile(43) = Subchunk2Size \ Byte4Divisor
      
      If BitsPerSample = 8 Then 'Samples are unsigned bytes; from 0 to 255
        For SampleNr = 0 To NumSamples - 1
          For ChannelNr = 0 To NumChannels - 1
            OutputFile(44 + BlockAlign * SampleNr + ChannelNr) = WaveData(ChannelNr, SampleNr) And Byte1Mask
          Next ChannelNr
        Next SampleNr
      ElseIf BitsPerSample = 16 Then 'Samples are 2's complement signed bytes; from -32768 to 32767
        For SampleNr = 0 To NumSamples - 1
          For ChannelNr = 0 To NumChannels - 1
            OutputFile(44 + BlockAlign * SampleNr + ChannelNr * BitsPerSample \ 8) = WaveData(ChannelNr, SampleNr) And Byte1Mask
            OutputFile(45 + BlockAlign * SampleNr + ChannelNr * BitsPerSample \ 8) = (WaveData(ChannelNr, SampleNr) And Byte2Mask) \ Byte2Divisor
          Next ChannelNr
        Next SampleNr
      End If
      CreateWaveArray = OutputFile
      
      Exit Function
    End Function
    
    Public Sub WriteWave(Path As String, WaveArray() As Byte)
      Dim ErrorNumber As Long
      
      On Error GoTo WriteWaveError
      Open Path For Input As #1
      Close #1
      
      If ErrorNumber = 0 Then 'File exists
        Kill Path             'Delete
      End If
      
      Open Path For Binary As #1
      Put #1, , WaveArray
      Close #1
      
    WriteWaveError:
      ErrorNumber = Err.Number
      Resume Next
    End Sub
    Get MediaEngine !!!
    Media Engine Download

  5. #5
    Constant Bitrate
    Join Date
    Mar 2008
    Posts
    162
    Well I currently have it working. When using the method above it seems to take several seconds to generate the tone on the fly.

    It is faster, and less prone to error (tapping the buttons fast), when I load up a .wav file.

    I have from 5Hz to 20000Hz sounds, and have made it easy to navigate through them.

    I also got the application loading up in RoadRunner. It works quite nicely.


    Now all I have to do is to polish up some of the GUI, add in the waveform images, and add in some Freq Sweeps to round it out.

    I had thought there would be more interest in this..but then I don't imagine a lot of people here go to SPL competitions.

    I'm sure to win 1rst place for style anyways lol

Similar Threads

  1. pc reboot on sd startup
    By duanes7 in forum StreetDeck
    Replies: 3
    Last Post: 12-14-2007, 08:55 AM
  2. Infill T3 prototypes of InFillCOM.dll
    By rburhum in forum StreetDeck
    Replies: 5
    Last Post: 05-22-2007, 12:31 AM
  3. Autodimming monitor after 2 seconds of inactivity. (Solution inside)
    By justintime in forum Software & Software Development
    Replies: 54
    Last Post: 02-01-2006, 01:48 AM
  4. New browsing function
    By TheUni in forum Road Runner
    Replies: 3
    Last Post: 10-15-2005, 11:03 AM

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
  •