home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 4_2005-2006.ISO / data / Zips / WaveIn_Rec2001136152006.psc / clsDSP.cls < prev    next >
Text File  |  2006-06-16  |  12KB  |  528 lines

  1. VERSION 1.0 CLASS
  2. BEGIN
  3.   MultiUse = -1  'True
  4.   Persistable = 0  'NotPersistable
  5.   DataBindingBehavior = 0  'vbNone
  6.   DataSourceBehavior  = 0  'vbNone
  7.   MTSTransactionMode  = 0  'NotAnMTSObject
  8. END
  9. Attribute VB_Name = "clsDSP"
  10. Attribute VB_GlobalNameSpace = False
  11. Attribute VB_Creatable = True
  12. Attribute VB_PredeclaredId = False
  13. Attribute VB_Exposed = False
  14. Option Explicit
  15.  
  16. ' Digital Signal Processing Class for 16 bit samples
  17. '
  18. ' Echo, Amplifier, Phase Shift, Graphical Equalizer
  19.  
  20. Private Const Pi                    As Single = 3.14159265358979
  21.  
  22. Private Enum DSP_VOL_UNIT
  23.     DSP_VOL_DECIBEL = 0
  24.     DSP_VOL_PERCENT
  25.     DSP_VOL_FACTOR
  26. End Enum
  27.  
  28. Public Enum DSP_FX
  29.     DSP_FX_ECHO = 2 ^ 0
  30.     DSP_FX_PHASE_SHIFT = 2 ^ 1
  31.     DSP_FX_AMPLIFY = 2 ^ 2
  32.     DSP_FX_EQUALIZER = 2 ^ 3
  33. End Enum
  34.  
  35. Private udeFXFlags                  As DSP_FX
  36.  
  37. '''' ECHO
  38. Private intEcho16()                 As Integer
  39. Private lngEchoPos16                As Long
  40. Private sngEchoLength16             As Single
  41. Private lngEchoLen                  As Long
  42. Private sngEchoAmp                  As Single
  43.  
  44. '''' AMPLIFIER
  45. Private lngVolume                   As Long
  46.  
  47. '''' PHASE SHIFT
  48. Private sngShX1                     As Single
  49. Private sngShX2                     As Single
  50. Private sngShX3                     As Single
  51. Private sngShX4                     As Single
  52.  
  53. Private sngShY1                     As Single
  54. Private sngShY2                     As Single
  55. Private sngShY3                     As Single
  56. Private sngShY4                     As Single
  57.  
  58. Private sngShMinWP                  As Single
  59. Private sngShMaxWP                  As Single
  60. Private sngShWp                     As Single
  61. Private sngShRate                   As Single
  62. Private sngShSweepFac               As Single
  63.  
  64. Private sngSetShDry                 As Single
  65. Private sngSetShWet                 As Single
  66. Private sngSetShFeedback            As Single
  67. Private sngSetShSweepRate           As Single
  68. Private sngSetShSweepRange          As Single
  69. Private sngSetShFreq                As Single
  70.  
  71. '''' EQUALIZER
  72. Private lngEQBands                  As Long
  73. Private sngBandGain()               As Single
  74. Private clsEQUBands()               As IIRFilter
  75.  
  76. '''' FORMAT
  77. Private lngSamplerate               As Long
  78. Private intChannels                 As Integer
  79.  
  80. Public Property Get samplerate( _
  81. ) As Long
  82.  
  83.     samplerate = lngSamplerate
  84. End Property
  85.  
  86. Public Property Let samplerate( _
  87.     ByVal lngSR As Long _
  88. )
  89.  
  90.     If lngSR < 1 Or lngSR > 96000 Then
  91.         Err.Raise 32000, "invalid samplerate"
  92.     Else
  93.         lngSamplerate = lngSR
  94.         UpdateFX
  95.     End If
  96. End Property
  97.  
  98. Public Property Get Channels( _
  99. ) As Integer
  100.  
  101.     Channels = intChannels
  102. End Property
  103.  
  104. Public Property Let Channels( _
  105.     ByVal intCh As Integer _
  106. )
  107.  
  108.     If intCh < 1 Or intCh > 2 Then
  109.         Err.Raise 32000, "invalid channels"
  110.     Else
  111.         intChannels = intCh
  112.         UpdateFX
  113.     End If
  114. End Property
  115.  
  116. Public Property Get EffectsUsed( _
  117. ) As DSP_FX
  118.  
  119.     EffectsUsed = udeFXFlags
  120. End Property
  121.  
  122. Public Property Let EffectsUsed( _
  123.     ByVal ude As DSP_FX _
  124. )
  125.  
  126.     udeFXFlags = ude
  127. End Property
  128.  
  129. Public Property Get EchoLength( _
  130. ) As Long
  131.  
  132.     EchoLength = lngEchoLen
  133. End Property
  134.  
  135. Public Property Let EchoLength( _
  136.     ByVal lngMS As Long _
  137. )
  138.  
  139.     lngEchoLen = lngMS
  140.     UpdateEcho
  141. End Property
  142.  
  143. Public Property Get EchoAmp( _
  144. ) As Single
  145.  
  146.     EchoAmp = sngEchoAmp
  147. End Property
  148.  
  149. Public Property Let EchoAmp( _
  150.     ByVal sngAmp As Single _
  151. )
  152.  
  153.     If sngAmp > 0.9 Then sngAmp = 0.9
  154.  
  155.     sngEchoAmp = sngAmp
  156.     UpdateEcho
  157. End Property
  158.  
  159. Public Property Get AmplifyDB( _
  160. ) As Long
  161.  
  162.     AmplifyDB = lngVolume
  163. End Property
  164.  
  165. Public Property Let AmplifyDB( _
  166.     ByVal lngVol As Long _
  167. )
  168.  
  169.     lngVolume = lngVol
  170. End Property
  171.  
  172. Public Property Get PhaseShiftWet( _
  173. ) As Single
  174.  
  175.     PhaseShiftWet = sngSetShWet
  176. End Property
  177.  
  178. Public Property Let PhaseShiftWet( _
  179.     ByVal sng As Single _
  180. )
  181.  
  182.     sngSetShWet = sng
  183.     UpdatePhaseShift
  184. End Property
  185.  
  186. Public Property Get PhaseShiftDry( _
  187. ) As Single
  188.  
  189.     PhaseShiftDry = sngSetShDry
  190. End Property
  191.  
  192. Public Property Let PhaseShiftDry( _
  193.     ByVal sng As Single _
  194. )
  195.  
  196.     sngSetShDry = sng
  197.     UpdatePhaseShift
  198. End Property
  199.  
  200. Public Property Get PhaseShiftFeedback( _
  201. ) As Single
  202.  
  203.     PhaseShiftFeedback = sngSetShFeedback
  204. End Property
  205.  
  206. Public Property Let PhaseShiftFeedback( _
  207.     ByVal sng As Single _
  208. )
  209.  
  210.     sngSetShFeedback = sng
  211.     UpdatePhaseShift
  212. End Property
  213.  
  214. Public Property Get PhaseShiftSweepRate( _
  215. ) As Single
  216.  
  217.     PhaseShiftSweepRate = sngSetShSweepRate
  218. End Property
  219.  
  220. Public Property Let PhaseShiftSweepRate( _
  221.     ByVal sng As Single _
  222. )
  223.  
  224.     sngSetShSweepRate = sng
  225.     UpdatePhaseShift
  226. End Property
  227.  
  228. Public Property Get PhaseShiftSweepRange( _
  229. ) As Single
  230.  
  231.     PhaseShiftSweepRange = sngSetShSweepRange
  232. End Property
  233.  
  234. Public Property Let PhaseShiftSweepRange( _
  235.     ByVal sng As Single _
  236. )
  237.  
  238.     sngSetShSweepRange = sng
  239.     UpdatePhaseShift
  240. End Property
  241.  
  242. Public Property Get PhaseShiftFrequency( _
  243. ) As Single
  244.  
  245.     PhaseShiftFrequency = sngSetShFreq
  246. End Property
  247.  
  248. Public Property Let PhaseShiftFrequency( _
  249.     ByVal sng As Single _
  250. )
  251.  
  252.     sngSetShFreq = sng
  253.     UpdatePhaseShift
  254. End Property
  255.  
  256. Public Property Get EqualizerBandFrequency( _
  257.     ByVal Index As Long _
  258. ) As Long
  259.  
  260.     EqualizerBandFrequency = clsEQUBands(Index).Frequency
  261. End Property
  262.  
  263. Public Property Get EqualizerBandGainDB( _
  264.     ByVal Index As Long _
  265. ) As Single
  266.  
  267.     EqualizerBandGainDB = sngBandGain(Index)
  268. End Property
  269.  
  270. Public Property Let EqualizerBandGainDB( _
  271.     ByVal Index As Long, _
  272.     ByVal gain_db As Single _
  273. )
  274.  
  275.     sngBandGain(Index) = gain_db
  276.     UpdateEqualizer
  277. End Property
  278.  
  279. Public Property Get EqualizerBands( _
  280. ) As Long
  281.  
  282.     EqualizerBands = lngEQBands
  283. End Property
  284.  
  285. Public Property Let EqualizerBands( _
  286.     ByVal lngBands As Long _
  287. )
  288.  
  289.     Dim i   As Long
  290.  
  291.     If lngBands < 1 Or lngBands > 10 Then
  292.         Err.Raise 32000, "Out Of Bounds!"
  293.     Else
  294.         lngEQBands = lngBands
  295.         ReDim clsEQUBands(lngEQBands - 1) As IIRFilter
  296.         ReDim sngBandGain(lngEQBands - 1) As Single
  297.  
  298.         For i = 0 To lngEQBands - 1
  299.             Set clsEQUBands(i) = New IIRFilter
  300.         Next
  301.  
  302.         UpdateEqualizer
  303.     End If
  304. End Property
  305.  
  306. Private Sub UpdateFX()
  307.     If lngSamplerate = 0 Then Exit Sub
  308.     If intChannels = 0 Then Exit Sub
  309.  
  310.     UpdateEcho
  311.     UpdatePhaseShift
  312.     UpdateEqualizer
  313. End Sub
  314.  
  315. ' http://www.codeproject.com/cs/media/cswavplayfx.asp
  316. Private Sub UpdatePhaseShift()
  317.     Dim range   As Double
  318.  
  319.     If lngSamplerate = 0 Then Exit Sub
  320.  
  321.     sngShMinWP = Pi * sngSetShFreq / lngSamplerate
  322.     range = 2 ^ sngSetShSweepRange
  323.     sngShMaxWP = Pi * sngSetShFreq * range / lngSamplerate
  324.     sngShRate = range ^ (2 * sngSetShSweepRate / lngSamplerate)
  325.  
  326.     sngShSweepFac = sngShRate
  327.     sngShWp = sngShMinWP
  328. End Sub
  329.  
  330. Private Sub UpdateEcho()
  331.     Dim lngEchoPoints   As Long
  332.  
  333.     If lngSamplerate = 0 Then Exit Sub
  334.  
  335.     lngEchoPoints = lngSamplerate / 1000 * lngEchoLen
  336.     ReDim intEcho16(lngEchoPoints - 1) As Integer
  337.  
  338.     sngEchoLength16 = sngEchoAmp
  339.     lngEchoPos16 = 0
  340. End Sub
  341.  
  342. Public Sub ProcessSamples( _
  343.     intSamples() As Integer _
  344. )
  345.  
  346.     Dim i   As Long
  347.  
  348.     If lngSamplerate = 0 Then Exit Sub
  349.     If intChannels = 0 Then Exit Sub
  350.  
  351.     If (udeFXFlags And DSP_FX_AMPLIFY) = DSP_FX_AMPLIFY Then
  352.         DSP_Process_ChangeVolume intSamples, lngVolume, DSP_VOL_DECIBEL
  353.     End If
  354.  
  355.     If (udeFXFlags And DSP_FX_ECHO) = DSP_FX_ECHO Then
  356.         DSP_Process_Echo intSamples
  357.     End If
  358.  
  359.     If (udeFXFlags And DSP_FX_PHASE_SHIFT) = DSP_FX_PHASE_SHIFT Then
  360.         DSP_Process_PhaseShift intSamples
  361.     End If
  362.  
  363.     If (udeFXFlags And DSP_FX_EQUALIZER) = DSP_FX_EQUALIZER Then
  364.         For i = 0 To lngEQBands - 1
  365.             clsEQUBands(i).ProcessSamples_16bit intSamples
  366.         Next
  367.     End If
  368. End Sub
  369.  
  370. Private Sub UpdateEqualizer()
  371.     Dim i           As Long
  372.     Dim lngFreq     As Long
  373.     Dim sngBW       As Single
  374.     Dim sngBFreq    As Single
  375.  
  376.     If lngSamplerate = 0 Then Exit Sub
  377.  
  378.     For i = 0 To lngEQBands - 1
  379.         lngFreq = lngSamplerate / 3
  380.  
  381.         sngBW = Log(lngFreq / 80#) / 4
  382.  
  383.         With clsEQUBands(i)
  384.             sngBFreq = 80# * (lngFreq / 80#) ^ (i / (lngEQBands - 1))
  385.  
  386.             .CreateBiquadIIR IIR_PEAK_EQ, _
  387.                              sngBandGain(i), _
  388.                              sngBFreq, _
  389.                              lngSamplerate, _
  390.                              sngBW
  391.         End With
  392.     Next
  393. End Sub
  394.  
  395. Private Sub DSP_Process_Echo( _
  396.     intSamples() As Integer _
  397. )
  398.  
  399.     Dim i   As Long
  400.  
  401.     For i = 0 To UBound(intSamples)
  402.         intSamples(i) = norm16(CLng(intSamples(i)) + intEcho16(lngEchoPos16))
  403.         intEcho16(lngEchoPos16) = intSamples(i) * sngEchoLength16
  404.  
  405.         lngEchoPos16 = lngEchoPos16 + 1
  406.         If lngEchoPos16 > UBound(intEcho16) Then
  407.             lngEchoPos16 = 0
  408.         End If
  409.     Next
  410. End Sub
  411.  
  412. Private Sub DSP_Process_ChangeVolume( _
  413.     intSamples() As Integer, _
  414.     ByVal value As Single, _
  415.     ByVal unit As DSP_VOL_UNIT _
  416. )
  417.  
  418.     Dim sngFactor   As Single
  419.     Dim sngResult   As Single
  420.     Dim i           As Long
  421.  
  422.     Select Case unit
  423.         Case DSP_VOL_DECIBEL
  424.             sngFactor = 10 ^ (value / 20)
  425.         Case DSP_VOL_PERCENT
  426.             sngFactor = value / 100
  427.         Case DSP_VOL_FACTOR
  428.             sngFactor = value
  429.     End Select
  430.  
  431.     For i = 0& To UBound(intSamples)
  432.         sngResult = intSamples(i) * sngFactor
  433.  
  434.         If sngResult > 32767# Then
  435.             intSamples(i) = 32767
  436.         ElseIf sngResult < -32768# Then
  437.             intSamples(i) = -32768
  438.         Else
  439.             intSamples(i) = CInt(sngResult)
  440.         End If
  441.     Next
  442. End Sub
  443.  
  444. ' http://www.codeproject.com/cs/media/cswavplayfx.asp
  445. Private Sub DSP_Process_PhaseShift( _
  446.     intSamples() As Integer _
  447. )
  448.  
  449.     Dim i   As Long
  450.     Dim k   As Single
  451.     Dim X1  As Single
  452.     Dim x   As Single
  453.     Dim y   As Single
  454.  
  455.     For i = 0& To UBound(intSamples)
  456.         x = intSamples(i) / 32767
  457.  
  458.         k = (1# - sngShWp) / (1# + sngShWp)
  459.  
  460.         X1 = x + sngSetShFeedback * sngShY4
  461.         sngShY1 = k * (sngShY1 + X1) - sngShX1
  462.         sngShX1 = X1
  463.         sngShY2 = k * (sngShY2 + sngShY1) - sngShX2
  464.         sngShX2 = sngShY1
  465.         sngShY3 = k * (sngShY3 + sngShY2) - sngShX3
  466.         sngShX3 = sngShY2
  467.         sngShY4 = k * (sngShY4 + sngShY3) - sngShX4
  468.         sngShX4 = sngShY3
  469.  
  470.         y = sngShY4 * sngSetShWet + x * sngSetShDry
  471.  
  472.         sngShWp = sngShWp * sngShSweepFac
  473.         If (sngShWp > sngShMaxWP) Then
  474.             sngShSweepFac = 1# / sngShRate
  475.         ElseIf (sngShWp < sngShMinWP) Then
  476.             sngShSweepFac = sngShRate
  477.         End If
  478.  
  479.         y = y * 32767
  480.  
  481.         If y > 32767 Then
  482.             intSamples(i) = 32767
  483.         ElseIf y < -32768 Then
  484.             intSamples(i) = -32768
  485.         Else
  486.             intSamples(i) = CInt(y)
  487.         End If
  488.     Next
  489. End Sub
  490.  
  491. Private Function norm16( _
  492.     ByVal dbl As Single _
  493. ) As Integer
  494.  
  495.     If dbl > 32767 Then
  496.         norm16 = 32767
  497.     ElseIf dbl < -32768 Then
  498.         norm16 = -32768
  499.     Else
  500.         norm16 = CInt(dbl)
  501.     End If
  502. End Function
  503.  
  504. Private Sub Class_Initialize()
  505.     Dim i   As Long
  506.  
  507.     sngEchoAmp = 0.4
  508.     lngEchoLen = 100                    ' ms
  509.     UpdateEcho
  510.  
  511.     lngVolume = 3                       ' dB
  512.  
  513.     sngSetShDry = 1
  514.     sngSetShWet = 1
  515.     sngSetShFeedback = 0.5
  516.     sngSetShSweepRate = 1
  517.     sngSetShSweepRange = 4
  518.     sngSetShFreq = 100                  ' Hz
  519.  
  520.     lngEQBands = 7
  521.     ReDim clsEQUBands(lngEQBands - 1) As IIRFilter
  522.     ReDim sngBandGain(lngEQBands - 1) As Single
  523.  
  524.     For i = 0 To lngEQBands - 1
  525.         Set clsEQUBands(i) = New IIRFilter
  526.     Next
  527. End Sub
  528.