home *** CD-ROM | disk | FTP | other *** search
/ Planet Source Code Jumbo …e CD Visual Basic 1 to 7 / 1_2002.ISO / Data / Zips / PcmRiff69031452002.psc / modRiff.bas < prev    next >
Encoding:
BASIC Source File  |  2002-04-04  |  18.8 KB  |  696 lines

  1. Attribute VB_Name = "modRiff"
  2. ' This module provides the necessary tools for generating
  3. '   basic RIFF (WAV) files in a standard PCM format from
  4. '   multiple sine waves
  5.  
  6. ' Code module and project created by "Urthman"
  7. '   http://www.jsent.biz/urthman/
  8. '   http://www.mp3.com/urthman/
  9.  
  10. Option Explicit
  11.  
  12. '   Bandwidth Selection ENUM
  13.  
  14. Enum BandWidth
  15.     NotSet = &H0            ' Not Set
  16.     EightBit = &H8          ' 8-bit
  17.     SixteenBit = &H10       ' 16-bit
  18.     TwentyFourBit = &H18    ' 24-bit
  19. End Enum
  20.  
  21. '   Internal data structures for sample streams
  22.  
  23. Private Type WaveForm1
  24.     Index As Long
  25.     Count As Long
  26.     Sample() As Double
  27. End Type
  28.  
  29. Private Type WaveForm2
  30.     Index As Long
  31.     Count As Long
  32.     Sample() As Long
  33. End Type
  34.  
  35. '=====================================================================================
  36. '   RIFF file format data chunks
  37. '=====================================================================================
  38.  
  39. '   RIFF chunk
  40.     
  41. Private Type RiffHead
  42.     Name As String * 4
  43.     Size As Long
  44.     Wave As String * 4
  45. End Type
  46.  
  47. '   Format Chunk
  48.  
  49. Private Type FormatChunk
  50.     Name As String * 4
  51.     Size As Long
  52.     AudioFormat As Integer
  53.     Channels As Integer
  54.     SampleRate As Long
  55.     ByteRate As Long
  56.     BlockAlign As Integer
  57.     BitsPerSample As Integer
  58. End Type
  59.  
  60. '   Wave Data Chunk
  61.  
  62. Private Type DataChunk
  63.     Name As String * 4
  64.     Size As Long
  65.     Data() As Byte
  66. End Type
  67.  
  68. '=====================================================================================
  69.  
  70. '   Temporary File variables
  71.  
  72. Dim PrtSize() As Long
  73. Dim PrtName() As String
  74. Dim PrtNumb As Long
  75. Dim PrtIndx As Integer
  76.  
  77. '   The RIFF structure data
  78.  
  79. Dim RIF As RiffHead
  80. Dim FMT As FormatChunk
  81. Dim WAV As DataChunk
  82.  
  83. '   Variables established by InitRiff - do not alter these values
  84. '   from the outside ... please read-only
  85.  
  86. Global Vmax As Double       ' Peak Value or preferred null value for silence
  87. Global bWidth As BandWidth  ' Resolution - bits per sample (Long)
  88. Global bRate As Long        ' Sample Rate
  89.  
  90. Dim WavIndx As Integer
  91.  
  92. '   Working Waveform Data
  93.  
  94. Dim Wave() As WaveForm1
  95. Dim WrkWave As WaveForm1
  96.  
  97. '   RIF File Name - for reference
  98.  
  99. Global RifName As String
  100.  
  101. '   Mixed output waveform
  102.  
  103. Global OutWave As WaveForm2
  104. ' Attenuate: This routine applies an attenuation value against a
  105. '   given wave generated by MakeSine. See also AttenuationValue
  106. '
  107. Sub Attenuate(Which%, ByVal Level As Double)
  108.  
  109. '   Which = which sine wave array
  110. '   Level = (from AttenuationValue) the new amplitude bandwidth
  111.  
  112. Dim AdjustBy As Double
  113. Dim aIndx&
  114.  
  115.     AdjustBy = Level / ((2 ^ bWidth) - 1)
  116.     
  117.     For aIndx = 0 To UBound(Wave(Which).Sample)
  118.         Wave(Which).Sample(aIndx) = (Wave(Which).Sample(aIndx) * AdjustBy)
  119.     Next
  120.  
  121. End Sub
  122. ' AttenuationValue: Given the decibel value to reduce a given signal by
  123. '   this function produces the necessary sample band-width peak value
  124. '
  125. Function AttenuationValue(ByVal Decibel As Double) As Double
  126.  
  127. '   Decibel = the decibel value relative to the full bandwidth
  128. '   Returns the equivalent attenuation band width
  129.  
  130. '   AttenuationValue(0) = no AttenuationValue = maximum volume
  131. '   AttenuationValue(2.93) = reduction value for -2.93 decibels
  132.  
  133. Dim DB As Double
  134.  
  135. ' To simplify programming, we'll force a negative value for adjustment
  136.     
  137.     DB = (Abs(Decibel) * -1)
  138.     AttenuationValue = (10 ^ (DB / 20)) * ((2 ^ bWidth) - 1)
  139.  
  140. End Function
  141. ' ClearWaves Initialize the arrays and variables for
  142. '   creating a new set of signal/waveforms
  143. '
  144. Sub ClearWaves()
  145.     
  146.     ReDim Wave(0)
  147.     ReDim Wave(0).Sample(0)
  148.     ReDim WrkWave.Sample(0)
  149.     ReDim OutWave.Sample(0)
  150.     
  151.     ReDim PrtSize(0)
  152.     ReDim PrtName(0)
  153.     
  154.     PrtSize(0) = 0
  155.     PrtName(0) = vbNullString
  156.     PrtNumb = 0
  157.     PrtIndx = 0
  158.     
  159.     WAV.Size = 0
  160.     ReDim WAV.Data(0)
  161.     WAV.Data(0) = 0
  162.     
  163.     DoEvents
  164.     
  165. End Sub
  166. ' HarmonicSeries: a DEMO routine for producing a harmonic series
  167. '   of a given frequency at staged attenuation values for 2 seconds
  168. '
  169. Private Sub HarmonicSeries(ByVal Freq As Double, SetSize As Integer)
  170.  
  171. Dim hIndx%
  172.  
  173. '   Note: an "InitRiff" needs to be run first to establish the
  174. '   sample rate and bandwidth. See the ReadMe subroutine
  175.  
  176.     If (bWidth = NotSet) Then
  177.         InitRiff 44100, SixteenBit
  178.     Else
  179.         ClearWaves
  180.     End If
  181.     
  182.     MakeSine hIndx, Freq, 2000
  183.     
  184.     For hIndx = 1 To SetSize
  185.         
  186. ' Create the harmonic wave series
  187.         
  188.         MakeSine hIndx, (Freq * (hIndx + 1)), 2000
  189.         
  190. ' Attenuate the harmonic wave by (3 * harmonic-number) decibels
  191.         
  192.         Attenuate hIndx, AttenuationValue(3 * hIndx)
  193.     Next
  194.     
  195.     MixWaves AttenuationValue(3)
  196.  
  197.     LoadRiff OutWave.Sample
  198.  
  199. '   SaveRiff [filename]
  200.  
  201. End Sub
  202. ' InitRiff initializes the sample-rate, bandwidth and RIFF header
  203. '   This also calls the ClearWaves routine to prep the arrays
  204. '
  205. Sub InitRiff(ByVal SamRate&, ByVal SamSize As BandWidth)
  206.     
  207. '   SamRate = Sample Rate (samples per second)
  208. '   SamSize = Bit Resolution (8, 16, 24)
  209.     
  210.     bWidth = SamSize
  211.     bRate = SamRate
  212.     
  213. '   Highest possible value in the bandwidth
  214.     
  215.     Vmax = Int((2 ^ (SamSize - 1)) - 1)
  216.  
  217. '   GROUP ID HEADER
  218.     
  219.     RIF.Name = "RIFF"
  220. '   RIF.Size is calculated in the SaveRiff routine
  221.     RIF.Wave = "WAVE"
  222.  
  223. '   FORMAT CHUNK
  224.  
  225.     FMT.Name = "fmt "
  226.     FMT.Size = 16
  227.     FMT.AudioFormat = 1
  228.     FMT.Channels = 1
  229.     FMT.SampleRate = SamRate
  230.     FMT.ByteRate = (SamRate * (SamSize / 8))
  231.     FMT.BlockAlign = (SamSize / 8)
  232.     FMT.BitsPerSample = SamSize
  233.  
  234.     WAV.Name = "data"
  235. '   WAV.Size is determined in the SaveRiff routine
  236. '   WAV.Data is assigned through the LoadRiff routine
  237.  
  238.     ClearWaves
  239.  
  240. End Sub
  241. ' LoadRiff takes an array of LONG sample values and breaks them
  242. '   out into a stream of bytes
  243. '
  244. Sub LoadRiff(WavData() As Long)
  245.  
  246. '   WavData() = an array of samples
  247.  
  248. Dim wIndx&, oIndx&
  249. Dim Bits(3) As Double
  250. Dim dNeed&
  251.  
  252.     oIndx = (bWidth / 8)
  253.     dNeed = (UBound(WavData) * oIndx) + (oIndx - 1)
  254.     
  255.     ReDim WAV.Data(dNeed)
  256.     
  257.     For wIndx = 0 To UBound(WAV.Data) Step oIndx
  258.         Select Case oIndx
  259.         Case 1                                          '   8-bit bandwidth
  260.             WAV.Data(wIndx) = CByte(WavData(wIndx))
  261.         Case 2                                          '   16-bit bandwidth
  262.             Bits(3) = Abs(WavData((wIndx / oIndx)))
  263.             Bits(1) = Int(Bits(3) / 256)
  264.             Bits(0) = Abs(Int(Bits(3) - (Bits(1) * 256)))
  265.             If (WavData((wIndx / oIndx)) < 0) Then Bits(1) = (255 - Bits(1))
  266.             WAV.Data(wIndx) = CByte(Bits(0))
  267.             WAV.Data(wIndx + 1) = CByte(Bits(1))
  268.         Case 3                                          '   24-bit bandwidth
  269.             Bits(3) = Abs(WavData((wIndx / oIndx)))
  270.             Bits(2) = Int(Bits(3) / 65536)
  271.             Bits(1) = Abs(Int((Bits(3) - (Bits(2) * 65536)) / 256))
  272.             Bits(0) = Abs(Int(Bits(3) - (Bits(2) * 65536) - (Bits(1) * 256)))
  273.             If (WavData((wIndx / oIndx)) < 0) Then Bits(2) = (255 - Bits(2))
  274.             WAV.Data(wIndx) = CByte(Bits(0))
  275.             WAV.Data(wIndx + 1) = CByte(Bits(1))
  276.             WAV.Data(wIndx + 2) = CByte(Bits(2))
  277.         End Select
  278.     Next
  279.     
  280. '   The data size
  281.     
  282.     WAV.Size = (UBound(WAV.Data) + 1)
  283.  
  284. End Sub
  285. Sub MakeSilence(ByVal MS As Long)
  286.  
  287. Dim SamCount&
  288.     
  289.     SamCount = (bRate * (MS / 1000))
  290.  
  291.     OutWave.Count = SamCount
  292.     ReDim OutWave.Sample(SamCount - 1)
  293.  
  294.     For OutWave.Index = 0 To (OutWave.Count - 1)
  295.         OutWave.Sample(OutWave.Index) = Vmax
  296.     Next
  297.  
  298. End Sub
  299. ' MakeSine calculates sine wave values against the sample rate and bandwidth
  300. '   given the frequency and duration of the signal in MilliSeconds
  301. '
  302. Function MakeSine(Which%, ByVal Freq As Double, ByVal MS As Long, Optional ByVal PhaseAngle As Double) As Boolean
  303.  
  304. '   Which = identifies waveform array (use sequentially starting with ZERO)
  305. '   Freq = Frequency; cycles per second
  306. '   MS = Milliseconds in duration
  307.  
  308. '   Returns TRUE if completed
  309.  
  310. Dim FreqCoeff As Double
  311. Dim PhaseAlign As Double            ' Phase Align
  312. Dim PhaseShift As Double            ' Phase Shift
  313. Dim SamCount&
  314.  
  315.     SamCount = (bRate * (MS / 1000))
  316.  
  317. '   NOT FINISHED BECAUSE ...
  318.  
  319.     PhaseShift = 0
  320.  
  321. '   ... I NEED TO CALCULATE SAMPLE-OFFSET FOR THE PhaseAngle:
  322. '   THE RELATIONSHIP BETWEEN PhaseShift AND PhaseAngle
  323. '   It needs to be a sample-count value relative to the angle
  324.     
  325.     If (Which > UBound(Wave)) Then ReDim Preserve Wave(Which)
  326.  
  327.     Wave(Which).Count = 0
  328.     Wave(Which).Index = 0
  329.     ReDim Wave(Which).Sample(0)
  330.     
  331. '   If the sample count is too small, we reject it
  332.     
  333.     If (SamCount < 10) Then Exit Function
  334.     
  335. '   I NEED TO DETERMINE A MAXIMUM SAMPLE COUNT BEFORE
  336. '   RUNNING OUT OF MEMORY
  337.     
  338.     FreqCoeff = (2 * (4 * Atn(1)) * (Freq / bRate))
  339.     Wave(Which).Count = SamCount
  340.     
  341.     For Wave(Which).Index = 0 To (SamCount - 1)
  342.         ReDim Preserve Wave(Which).Sample(Wave(Which).Index)
  343.         PhaseAlign = (Wave(Which).Index + PhaseShift)
  344.         Wave(Which).Sample(Wave(Which).Index) = 0 - (Vmax * Sin(FreqCoeff * PhaseAlign))
  345.     Next
  346.  
  347.     MakeSine = True
  348.  
  349. End Function
  350.  
  351.  
  352. ' MakeSineMod calculates modulated sine wave values against the sample
  353. '   rate and bandwidth given the frequency and duration of the signal in
  354. '   MilliSeconds and adjusts the output by a modulation frequency and
  355. '   amplitude.
  356. '
  357. Function MakeSineMod(Which%, ByVal Freq As Double, ByVal MS As Long, ByVal ModFreq As Double, ByVal ModAmp As Double) As Boolean
  358.  
  359. '   Which = identifies waveform array (use sequentially starting with ZERO)
  360. '   Freq = Frequency; cycles per second
  361. '   MS = Milliseconds in duration
  362. '   ModFreq = Modulation Frequency
  363. '   ModAmp = Modulation Amplitude
  364.  
  365. '   Returns TRUE if completed
  366.  
  367. Dim FreqCoeff As Double
  368. Dim FreqShift As Double
  369. Dim PhaseAlign As Double            ' Phase Align
  370. Dim PhaseShift As Double            ' Phase Shift
  371. Dim SamCount&
  372.  
  373.     SamCount = (bRate * (MS / 1000))
  374.  
  375.     If (Which > UBound(Wave)) Then ReDim Preserve Wave(Which)
  376.  
  377.     Wave(Which).Count = 0
  378.     Wave(Which).Index = 0
  379.     ReDim Wave(Which).Sample(0)
  380.     
  381. '   If the sample count is too small, we reject it
  382.     
  383.     If (SamCount < 10) Then Exit Function
  384.     
  385. '   I NEED TO DETERMINE A MAXIMUM SAMPLE COUNT BEFORE
  386. '   RUNNING OUT OF MEMORY
  387.     
  388.     FreqCoeff = (2 * (4 * Atn(1)) * (Freq / bRate))
  389.     FreqShift = (2 * (4 * Atn(1)) * (ModFreq / bRate))
  390.     
  391.     Wave(Which).Count = SamCount
  392.     
  393.     For Wave(Which).Index = 0 To (SamCount - 1)
  394.         ReDim Preserve Wave(Which).Sample(Wave(Which).Index)
  395.         
  396. ' CALCULATE THE PhaseShift BASED ON THE ModFreq AND ModAmp VALUES
  397. ' AND APPLY TO AN ADJUSTMENT AGAINST PhaseAligh
  398.         
  399.         PhaseShift = (ModAmp * Sin(FreqShift * Wave(Which).Index))
  400.         
  401.         PhaseAlign = (Wave(Which).Index + PhaseShift)
  402.         Wave(Which).Sample(Wave(Which).Index) = 0 - (Vmax * Sin(FreqCoeff * PhaseAlign))
  403.     Next
  404.  
  405.     MakeSineMod = True
  406.  
  407. End Function
  408. ' MixWaves will gather all of the waveforms generated by MakeSine
  409. '   and mix them into a single stream reduced to within the
  410. '   normalization peak value (in bits)
  411. '
  412. Sub MixWaves(ByVal Peak As Double)
  413.  
  414. '   Peak = maximum amplitude in bits (no higher than Vmax)
  415. '   Use (and see) the AttenuationValue function to get the peak value
  416.  
  417. Dim Adjust As Double, WorkData As Long
  418. Dim MaxVal As Double, MinVal As Double
  419. Dim wIndx%, wDivis As Double
  420.  
  421.     WrkWave.Count = 0
  422.     WrkWave.Index = 0
  423.     ReDim WrkWave.Sample(0)
  424.  
  425.     MinVal = 0: MaxVal = 0
  426.  
  427. '   [1] Get the sample count
  428.  
  429.     For wIndx = 0 To UBound(Wave)
  430.         If (WrkWave.Count < Wave(wIndx).Count) Then WrkWave.Count = Wave(wIndx).Count
  431.     Next
  432.     
  433.     If WrkWave.Count < 100 Then Exit Sub
  434.     ReDim WrkWave.Sample(WrkWave.Count - 1)
  435.  
  436. '   Mixing the waves together consists primarily of averaging the values
  437.  
  438.     wDivis = (UBound(Wave) + 1)
  439.  
  440. '   [2] Add the wave values together at the same strength
  441.         
  442.     For WrkWave.Index = 0 To (WrkWave.Count - 1)
  443.         WrkWave.Sample(WrkWave.Index) = 0
  444.         
  445. '           ... even if one signal runs out - it keeps combining the values
  446. '               and assumes the one that run out has a signal value of zero
  447.         
  448.         For wIndx = 0 To UBound(Wave)
  449.             If (wIndx <= UBound(Wave(wIndx).Sample)) Then _
  450.                 WrkWave.Sample(WrkWave.Index) = (WrkWave.Sample(WrkWave.Index) + Wave(wIndx).Sample(WrkWave.Index))
  451.         Next
  452.         
  453. '           divide by the number of waves being added
  454.         
  455.         WrkWave.Sample(WrkWave.Index) = (WrkWave.Sample(WrkWave.Index) / wDivis)
  456.  
  457. '   [3] Determine the Min and Max Normalizing Values at the same time
  458.     
  459.         If (WrkWave.Sample(WrkWave.Index) > MaxVal) Then MaxVal = WrkWave.Sample(WrkWave.Index)
  460.         If ((WrkWave.Sample(WrkWave.Index) * -1) > MinVal) Then MinVal = (WrkWave.Sample(WrkWave.Index) * -1)
  461.     Next
  462.  
  463. '   [4] Establish the normalizing value
  464.  
  465.     Adjust = 1
  466.     
  467.     If (MaxVal > MinVal) Then
  468.         If (MaxVal > 0) Then Adjust = ((Peak * 0.5) / MaxVal)
  469.     Else
  470.         If (MinVal > 0) Then Adjust = ((Peak * 0.5) / MinVal)
  471.     End If
  472.     
  473. '   [5] Apply the normalizing value
  474.     
  475.     For WrkWave.Index = 0 To (WrkWave.Count - 1)
  476.         WrkWave.Sample(WrkWave.Index) = (WrkWave.Sample(WrkWave.Index) * Adjust)
  477.     Next
  478.  
  479. '   [6] Align 8-bit samples to monopolar output.
  480.  
  481.     OutWave.Count = WrkWave.Count
  482.     ReDim OutWave.Sample(OutWave.Count - 1)
  483.  
  484.     For OutWave.Index = 0 To (OutWave.Count - 1)
  485.         If (bWidth = EightBit) Then             '8-bit samples are not bipolar
  486.             WorkData = Int(WrkWave.Sample(OutWave.Index) + (Vmax + 1))
  487.         Else                                    ' 16 and 24 bit samples are
  488.             WorkData = Int(WrkWave.Sample(OutWave.Index))
  489.         End If
  490.         OutWave.Sample(OutWave.Index) = WorkData
  491.     Next
  492.  
  493. End Sub
  494. Function NextSine(ByVal Freq As Double, ByVal MS As Long, Optional ByVal PhaseAngle As Double) As Integer
  495.  
  496. Dim nIndx%
  497.  
  498.     If (UBound(Wave) = 0) And (Wave(0).Count = 0) Then
  499.         nIndx = 0
  500.     Else
  501.         nIndx = (UBound(Wave) + 1)
  502.     End If
  503.     
  504.     MakeSine nIndx, Freq, MS, PhaseAngle
  505.     NextSine = UBound(Wave)
  506.  
  507. End Function
  508. Function NextSineMod(ByVal Freq As Double, ByVal MS As Long, ByVal ModFreq As Double, ByVal ModAmp As Double) As Integer
  509.  
  510. Dim nIndx%
  511.  
  512.     If (UBound(Wave) = 0) And (Wave(0).Count = 0) Then
  513.         nIndx = 0
  514.     Else
  515.         nIndx = (UBound(Wave) + 1)
  516.     End If
  517.     
  518.     MakeSineMod nIndx, Freq, MS, ModFreq, ModAmp
  519.     NextSineMod = UBound(Wave)
  520.  
  521. End Function
  522. Private Sub ReadMe()
  523.  
  524. ' See also the DEMO subroutine HarmonicSeries
  525.  
  526. '--------------------------------------------------------------------
  527.  
  528. '   Fundamental Application:
  529.  
  530. ' Initialize the RIFF variables and buffers for a given sample rate
  531. '   and band width:
  532.  
  533. '   InitRiff SampleRate, BandWidth
  534.  
  535. ' Build the SINE wave collection:
  536.  
  537. '   MakeSine 0, Frequency0, Duration, PhaseAngle
  538. '   MakeSine 1, Frequency1, Duration, PhaseAngle
  539. '
  540. '           ... etc ...
  541. '
  542. '   MakeSine N, FrequencyN, Duration, PhaseAngle
  543.  
  544. ' Mix the waves together:
  545.  
  546. '   MixWaves AttenuationValue(X)
  547.  
  548. ' Save the data:
  549.  
  550. '   LoadRiff OutWave.Sample
  551. '   SaveRiff "FileName.wav"
  552.  
  553. ' Reinitialize the variables for another wave using the same
  554. '   sample rate and band width:
  555.  
  556. '   ClearWaves
  557.  
  558. '--------------------------------------------------------------------
  559.  
  560. ' Prior to mixing the waves, they can be attenuated independently of the mix:
  561.  
  562. '   MakeSine 0, Frequency0, Duration, PhaseAngle
  563.  
  564. '       ... produces a sine wave at maximum saturation
  565.  
  566. '   Attenuate 0, AttenuationValue(3)
  567.  
  568. '       ... will adjust Wave(0) by -3db
  569.  
  570. '   MixWaves AttenuationValue(3)
  571.  
  572. '       ... will apply an addition -3db level reduction
  573.  
  574. '--------------------------------------------------------------------
  575.  
  576. '   StashChunk Usage: Permits the creation of large waves whose
  577. '   size would exceed the memory resources of a given machine
  578.  
  579. '   ... build part into PartBuffer
  580.  
  581. '   LoadRiff OutWave.Sample
  582. '   StashChunk
  583.  
  584. '   ... build next part
  585.  
  586. '   LoadRiff OutWave.Sample
  587. '   StashChunk
  588.  
  589. '   SaveRiff "FileName.wav"
  590.  
  591. '--------------------------------------------------------------------
  592.  
  593. End Sub
  594. ' SaveRiff will write the PCM file to disk. (See also StashChunk)
  595. '
  596. Sub SaveRiff(SaveName$)
  597.  
  598. '   SaveName = file name, including path and ".wav" extension
  599.  
  600. Dim RifIndx%, pIndx%
  601. Dim PrtStrg$
  602.     
  603. '   Accumulate the fragment sizes IF StashChunk was used
  604.     
  605.     If (PrtNumb > 0) Then
  606.         WAV.Size = 0
  607.         For pIndx = 0 To UBound(PrtSize)
  608.             WAV.Size = (WAV.Size + PrtSize(pIndx))
  609.         Next
  610.     End If
  611.     
  612. '   The total size of the wave data
  613.     
  614.     RIF.Size = (4 + (8 + FMT.Size) + (8 + WAV.Size))
  615.     
  616. '   Eliminate any existing file with the same name ...
  617.     
  618.     RifName = SaveName
  619.     If (RifName > vbNullString) Then
  620.         If FileExist(RifName) Then Kill RifName
  621.     Else
  622.         MsgBox "No File Name"       ' ... if, of course, there is one
  623.         End
  624.     End If
  625.     
  626.     RifIndx = FreeFile
  627.     Open RifName For Binary As RifIndx
  628.     
  629. '   RIF CHUNK
  630.     
  631.     Put #RifIndx, , RIF.Name
  632.     Put #RifIndx, , RIF.Size
  633.     Put #RifIndx, , RIF.Wave
  634.     
  635. '   FORMAT CHUNK
  636.     
  637.     Put #RifIndx, , FMT.Name
  638.     Put #RifIndx, , FMT.Size
  639.     Put #RifIndx, , FMT.AudioFormat
  640.     Put #RifIndx, , FMT.Channels
  641.     Put #RifIndx, , FMT.SampleRate
  642.     Put #RifIndx, , FMT.ByteRate
  643.     Put #RifIndx, , FMT.BlockAlign
  644.     Put #RifIndx, , FMT.BitsPerSample
  645.     
  646. '   DATA CHUNK
  647.  
  648.     Put #RifIndx, , WAV.Name
  649.     Put #RifIndx, , WAV.Size
  650.     
  651. '   If StashChunk had been used, we need to read and write
  652. '   each fragment contiguously
  653.     
  654.     If (PrtNumb = 0) Then
  655.         Put #RifIndx, , WAV.Data
  656.     Else
  657.         For pIndx = 0 To UBound(PrtName)
  658.             PrtStrg = Space(PrtSize(pIndx))
  659.             PrtIndx = FreeFile
  660.             Open PrtName(pIndx) For Binary As PrtIndx
  661.             Get #PrtIndx, , PrtStrg
  662.             Close #PrtIndx
  663.             Put #RifIndx, , PrtStrg
  664.             DoEvents
  665.             Kill PrtName(pIndx)
  666.         Next
  667.     End If
  668.     Close #RifIndx
  669.  
  670. '   All Done!
  671.  
  672. End Sub
  673. ' StashChunk - in the event of a large sample, StashChunk allows
  674. '   saving parts of the whole wave data into temporary fragments
  675. '   which are accumulated later by the SaveRiff routine
  676. '
  677. Sub StashChunk()
  678.  
  679.     ReDim Preserve PrtName(PrtNumb)
  680.     ReDim Preserve PrtSize(PrtNumb)
  681.     
  682.     PrtName(PrtNumb) = (App.Path & "\CHUNK." & Format(PrtNumb, "000"))
  683.  
  684.     If (Dir(PrtName(PrtNumb)) > vbNullString) Then Kill PrtName(PrtNumb)
  685.     
  686.     PrtIndx = FreeFile
  687.     Open PrtName(PrtNumb) For Binary As PrtIndx
  688.     Put #PrtIndx, , WAV.Data
  689.     Close #PrtIndx
  690.  
  691.     PrtSize(PrtNumb) = WAV.Size
  692.  
  693.     PrtNumb = (PrtNumb) + 1
  694.  
  695. End Sub
  696.