Results 1 to 40 of 181

Thread: Sugestions or Comments about my Sound Tutorial

Hybrid View

  1. #1
    Lively Member rm_03's Avatar
    Join Date
    Aug 2004
    Posts
    92

    Re: Sugestions or Comments about my Sound Tutorial

    Not much left...

    FFT with windowing:

    Code:
    Option Explicit
    
    Private Const Pi        As Single = 3.14159265358979
    Private Const AngleNum  As Single = 2 * Pi
    
    Private lngPow2(31)     As Long
    
    Public Enum FFT_WINDOW
        WINDOW_FUNC_NONE
        WINDOW_FUNC_HANNING
        WINDOW_FUNC_HAMMING
        WINDOW_FUNC_BLACKMAN
    End Enum
    
    ' http://www.fullspectrum.com/deeth/main.html
    Public Sub FastFourierTransform( _
        NumSamples As Long, _
        RealIn() As Integer, _
        RealOut() As Single, _
        Optional wnd As FFT_WINDOW = WINDOW_FUNC_NONE _
    )
    
        Dim NumBits     As Long
    
        Dim Rev         As Long
        Dim index       As Long
    
        Dim i           As Long, j          As Long
        Dim k           As Long, n          As Long
    
        Dim BlockSize   As Long, BlockEnd   As Long
    
        Dim DeltaAngle  As Single, DeltaAr  As Single
        Dim Alpha       As Single, Beta     As Single
    
        Dim TR          As Single, TI       As Single
        Dim AR          As Single, AI       As Single
    
        Dim dblWnd()    As Single
    
        Dim imagout()   As Single
        ReDim imagout(NumSamples - 1) As Single
    
        dblWnd = CreateWindow(wnd, NumSamples)
    
        For i = 0 To 16
            If (NumSamples And lngPow2(i)) <> 0 Then
                NumBits = i
                Exit For
            End If
        Next
    
        For i = 0 To (NumSamples - 1)
            index = i
            Rev = 0
            For k = 0 To NumBits - 1
                Rev = (Rev * 2) Or (index And 1)
                index = index \ 2
            Next
            j = Rev
    
            RealOut(j) = RealIn(i) * dblWnd(i)
        Next
    
        BlockEnd = 1
        BlockSize = 2
    
        Do While BlockSize <= NumSamples
            DeltaAngle = AngleNum / BlockSize
            Alpha = Sin(0.5 * DeltaAngle)
            Alpha = 2# * Alpha * Alpha
            Beta = Sin(DeltaAngle)
    
            For i = 0 To NumSamples - 1 Step BlockSize
                AR = 1#
                AI = 0#
    
                j = i
                For n = 0 To BlockEnd - 1
                    k = j + BlockEnd
                    TR = AR * RealOut(k) - AI * imagout(k)
                    TI = AI * RealOut(k) + AR * imagout(k)
                    RealOut(k) = RealOut(j) - TR
                    imagout(k) = imagout(j) - TI
                    RealOut(j) = RealOut(j) + TR
                    imagout(j) = imagout(j) + TI
                    DeltaAr = Alpha * AR + Beta * AI
                    AI = AI - (Alpha * AI - Beta * AR)
                    AR = AR - DeltaAr
                    j = j + 1&
                Next
    
            Next
    
            BlockEnd = BlockSize
            BlockSize = BlockSize * 2&
        Loop
    End Sub
    
    Public Sub InitPower2()
        Dim i   As Long
        For i = 0 To 30
            lngPow2(i) = 2 ^ i
        Next
        lngPow2(31) = &H80000000
    End Sub
    
    Public Function CreateWindow( _
        wnd As FFT_WINDOW, _
        ByVal Length As Long _
    ) As Single()
    
        Dim dblOut()    As Single
        Dim i           As Long
    
        ReDim dblOut(Length - 1) As Single
    
        Select Case wnd
    
            Case WINDOW_FUNC_NONE
                For i = 0 To Length - 1
                    dblOut(i) = 1
                Next
    
            Case WINDOW_FUNC_HANNING
                For i = 0 To Length - 1
                    dblOut(i) = 0.5 * (1 - Cos(i * 2 * Pi / (Length - 1)))
                Next
    
            Case WINDOW_FUNC_HAMMING
                For i = 0 To Length - 1
                    dblOut(i) = 0.54 - (0.46 * Cos((i) * 2 * Pi / (Length - 1)))
                Next
    
            Case WINDOW_FUNC_BLACKMAN
                For i = 0 To Length - 1
                    dblOut(i) = 0.42 - (0.5 * Cos((i) * 2 * Pi / (Length - 1))) + (0.08 * Cos((i) * 4 * Pi / (Length - 1)))
                Next
    
        End Select
    
        CreateWindow = dblOut
    End Function
    Usage:

    Code:
    InitPower2  ' needs to be called only once
    
    FastFourierTransform 1024, intSamplesInput, sngSamplesOutput, WINDOW_FUNC_HANNING
    Will apply an Hanning window on intSamplesInput and return the
    frequency domain in sngSamplesOutput (NumSamples has to be 2^N),
    where each element in the array represents samplerate / NumSamples bandwidth, if I remember correctly.

    Changing volume:
    Code:
    Public Enum VOL_UNIT
        VOL_DECIBEL
        VOL_PERCENT
        VOL_FACTOR
    End Enum
    
    Public Sub ChangeVolume( _
        intSamples() As Integer, _
        ByVal datalen As Long, _
        ByVal value As Single, _
        ByVal unit As VOL_UNIT _
    )
    
        Dim sngFactor   As Single
        Dim sngResult   As Single
        Dim i           As Long
    
        Select Case unit
            Case VOL_DECIBEL
                sngFactor = 10 ^ (value / 20)
            Case VOL_PERCENT
                sngFactor = value / 100
            Case VOL_FACTOR
                sngFactor = value
        End Select
    
        For i = 0& To datalen
            sngResult = intSamples(i) * sngFactor
    
            If sngResult > 32767# Then
                intSamples(i) = 32767
            ElseIf sngResult < -32768# Then
                intSamples(i) = -32768
            Else
                intSamples(i) = CInt(sngResult)
            End If
        Next
    End Sub
    Usage:

    Code:
    ChangeVolume intSamples, UBound(intSamples), 6, VOL_DECIBEL
    Will boost the volume by 6 dB.

    Echo:

    Code:
    Private intEcho()           As Integer
    Private lngEchoPos          As Long
    Private lngEchoLength       As Single
    
    Public Sub DSPEcho( _
        intSamples() As Integer, _
        ByVal datalength As Long _
    )
    
        Dim i   As Long
    
        For i = 0 To datalength
            intSamples(i) = norm(CLng(intSamples(i)) + intEcho(lngEchoPos))
            intEcho(lngEchoPos) = intSamples(i) * lngEchoLength
    
            lngEchoPos = lngEchoPos + 1
            If lngEchoPos > UBound(intEcho) Then
                lngEchoPos = 0
            End If
        Next
    End Sub
    
    Public Sub DSPEchoSettings( _
        ByVal samplerate As Long, _
        ByVal echo_length_ms As Long, _
        ByVal echo_length As Single _
    )
    
        Dim lngEchoPoints   As Long
    
        lngEchoPoints = samplerate / 1000 * echo_length_ms
        ReDim intEcho(lngEchoPoints - 1) As Integer
    
        lngEchoLength = echo_length
    
        lngEchoPos = 0
    End Sub
    Usage:

    Code:
    DSPEchoSettings 44100, 500, 0.4
    
    DSPEcho intSamples, UBound(intSamples)
    Will add an echo to the signal wich is 500 ms long and will be multiplied by 0.4 after each reverb.

    Decibel Full Scale:
    Code:
    Public Function dBFS(ByVal amplitude As Long) As Double
        If amplitude = 0 Then
            dBFS = -96
        Else
            dBFS = 20 * ((Log(Abs(amplitude) / 32768)) / Log(10))
        End If
    End Function
    Will return a value from -96 to 0 dBFS.

    I also have written encoders and decoders for wav/mp3/ape/ogg/wma/cda (for a streaming player), but with german comments, if you're interested.
    I just don't have the time to translate it all, else I would've already posted it at PSC.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Sugestions or Comments about my Sound Tutorial

    I also have some FFT code in C++ and VB that I used before, but I never had time to look at it, and understand how it works, and how to use it in practical cases.
    I only used it before to show that "wave preview" thing while the music is recorded/played...
    From what I know you can do neet stuff like sound recognition with FFT, but never figured it out how to implement it for that.

    The echo and volume thing I already know how to do, it's easy... if you look at "My Objectives" I already have those listed there...
    Quote Originally Posted by rm_03
    I also have written encoders and decoders for wav/mp3/ape/ogg/wma/cda (for a streaming player), but with german comments, if you're interested.
    I just don't have the time to translate it all, else I would've already posted it at PSC.
    Yes, I am interested... I don't care if it's in another language, as long as the code is clearly written, I will understand what is going on (as long as I have enough time). I actually never understood someone else's comments.

    What anoys me with comments is something like:

    Open "c:\some file.txt" for binary as #1 ' Open the file

    I'm like: "Really... I thought you close the file with that statement..."
    So comments don't matter to me.

    But I have to admit, I'm doing the same thing in my tutorial

  3. #3
    Lively Member rm_03's Avatar
    Join Date
    Aug 2004
    Posts
    92

    Re: Sugestions or Comments about my Sound Tutorial

    The basic idea behind the Fourier Transformation is to split a periodic function into some sine and cosine functions.
    That way you can also obtain the frequencies of an audio signal.
    The output array of the FFT function I posted above contains:

    element 0: d/c offset (whatever that is...)
    element 1 - n/2: frequencies
    element n/2 - n: again frequencies, but in reversed order (maybe cosine values)

    each element in 1 - n/2 is a frequency band with a bandwidth of samplerate/num_samples Hz.
    So, the more samples you use, the more accurate it will get, but also the slower.
    Also, the FFT is fastest with 2^n samples.
    I use the FFT for a Winamp like visualisation of audio, so I only use 512 samples (very fast compiled).

    I don't think you need to know more about the FFT (maybe a bit about the DCT).

    I don't care if it's in another language
    Of course the DLLs wich do the actual job are not written in VB.
    Anyway, I attached my project. The UI of the test projects is german,
    but I think it's easy to guess.
    Attached Files Attached Files

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Sugestions or Comments about my Sound Tutorial

    What do you guys think of the tutorial so far ?

    (posting also to bump...)

  5. #5
    Lively Member rm_03's Avatar
    Join Date
    Aug 2004
    Posts
    92

    Re: Sugestions or Comments about my Sound Tutorial

    I really like the resampling function, I tried that before but failed on downsampling, although I havn't tested yours yet.
    It looks like you're using linear interpolation, cubic or Hermite interpolation should increase the quality.
    (http://astronomy.swin.edu.au/~pbourk...ion/index.html)
    I've also heard you should do low pass filtering to remove frequencies above the new Nyquist frequency when downsampling, but never dealed with it.

    Anyway, I've just ported a Goertzel algorithm (Fourier transformation, but only for 1 frequency)
    for tone detection to VB,
    maybe you can use it for your tone detection topic:

    Code:
    Function Goertzel( _
        sngData() As Single, _
        ByVal N As Long, _
        ByVal freq As Single, _
        ByVal sampr As Long _
    ) As Single
    
        Dim Skn     As Single
        Dim Skn1    As Single
        Dim Skn2    As Single
        Dim c       As Single
        Dim c2      As Single
        Dim i       As Long
    
        c = 2 * PI * freq / sampr
        c2 = Cos(c)
    
        For i = 0 To N - 1
            Skn2 = Skn1
            Skn1 = Skn
            Skn = 2 * c2 * Skn1 - Skn2 + sngData(i)
        Next
    
        Goertzel = Skn - Exp(-c) * Skn1
    End Function
    
    Function power(ByVal value As Single) As Single
        power = 20 * Log(Abs(value)) / Log(10)
    End Function
    Usage: (returns dB of 8000 Hz in the signal at 44100 samples/s)
    Code:
    dB = power(Goertzel(sngSignal, UBound(sngSignal) + 1, 8000, 44100))
    I also did some testing with DTMF tone detection,
    it can detect a generated tone in 0.01 seconds in the IDE
    (compiled with optimizations 0.001 s), which is pretty fast on a P3 550 Mhz, I think.

  6. #6

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Sugestions or Comments about my Sound Tutorial

    Quote Originally Posted by rm_03
    It looks like you're using linear interpolation, cubic or Hermite interpolation should increase the quality.
    (http://astronomy.swin.edu.au/~pbourk...ion/index.html)
    I've also heard you should do low pass filtering to remove frequencies above the new Nyquist frequency when downsampling, but never dealed with it.
    Thanks for the link.

    I implemented the Cubic and Hermite interpolation from the link you gave me, but I don't see significant diferences between linear and the other 2.

    Hermite looks best compared to the original.

    I will make another test program that will convert wave files and save them into new ones, so that I can hear the diference.

    I attached a test project, please take a look at it, and tell me what you think ?

    I did not have time to take a look at the rest of the code you gave me. I'm very busy lately.
    Attached Files Attached Files

  7. #7
    Lively Member rm_03's Avatar
    Join Date
    Aug 2004
    Posts
    92

    Re: Sugestions or Comments about my Sound Tutorial

    I implemented the Cubic and Hermite interpolation from the link you gave me, but I don't see significant diferences between linear and the other 2.
    Take a look at this:
    http://musicdsp.org/files/other001.gif

    I attached a test project, please take a look at it, and tell me what you think ?
    Very nice stuff, hopefully this has some real time capabilities

  8. #8

    Thread Starter
    PowerPoster
    Join Date
    Feb 2002
    Location
    Canada, Toronto
    Posts
    5,803

    Re: Sugestions or Comments about my Sound Tutorial

    Quote Originally Posted by rm_03
    Usage: (returns dB of 8000 Hz in the signal at 44100 samples/s)
    Code:
    dB = power(Goertzel(sngSignal, UBound(sngSignal) + 1, 8000, 44100))
    I also did some testing with DTMF tone detection,
    it can detect a generated tone in 0.01 seconds in the IDE
    (compiled with optimizations 0.001 s), which is pretty fast on a P3 550 Mhz, I think.
    I finally had time to try it.

    I'm speechless, very nice !

    It's soo precise !
    I tried with a dual tone with frequencies (tones from the phone): 770 Hz and 1209 Hz (wich coresponds to #4 on the phone)

    I made a short program that tests with all the frequencies from the phone, and I got this:
    First number is the frequency and in brackets is the dB
    Test1:
    350(075.87) 440(060.86) 480(046.48) 620(076.66) 697(077.03) 770(171.13) 852(068.98) 941(042.27) 1209(171.14) 1336(067.06) 1477(062.78)
    Test2:
    350(075.87) 440(060.86) 480(046.48) 620(076.66) 697(077.03) 771(111.53) 852(068.98) 941(042.27) 1209(171.14) 1336(067.06) 1477(062.78)

    If you notice In the first test for the frequency 770 the volume is 171, and for frequency 1209 is the same.
    The second test, I changed it to test for 771 Hz instead of 770 Hz, and the result is 111 dB

    The diference in frequency is only 1 Hz, but a very big diference in dB (wich is very good)

    Pretty fast too...

    Though I made the test with digitaly created wave files (wich have perfect quality), not actual tone from the phone. I want to test for that too, but I don't have time right now.

  9. #9
    PowerPoster
    Join Date
    Feb 2006
    Location
    East of NYC, USA
    Posts
    5,691

    Re: Sugestions or Comments about my Sound Tutorial

    Quote Originally Posted by rm_03
    element 0: d/c offset (whatever that is...)
    That tells you where the center of the waveform is, relative to a reference point (usually 0 volts, or ground). A pure AC waveform will have a 0 DC offset, but signals can "ride on" a fixed (or even varying, in which case the DC offset will vary with time) DC level.

    @CVMichael:
    Look in the AllAPI API Guide - they're in there, with VB6 (and VB.net) code.
    The most difficult part of developing a program is understanding the problem.
    The second most difficult part is deciding how you're going to solve the problem.
    Actually writing the program (translating your solution into some computer language) is the easiest part.

    Please indent your code and use [HIGHLIGHT="VB"] [/HIGHLIGHT] tags around it to make it easier to read.

    Please Help Us To Save Ana

Posting Permissions

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



Click Here to Expand Forum to Full Width