-
Sugestions or Comments about my Sound Tutorial
The tutorial (under construction):
http://www.vbforums.com/showthread.php?t=388562
Please post any sugestions or comments about my tutorial here.
What would you like to see in my tutorial ? (keep in mind that it is about sound using DirectXSound)
Any comments about what I already have ? something that needs more explaining, or not clear enough ?
Did I make any mistakes in that thread ? am I saying something that is not true/wrong ?
Keep in mind that it is under construction, and it will be for a long time. I'm doing this in my free time (at work, and home).
-
Re: Sugestions or Comments about my Sound Tutorial
You said,
Quote:
Originally Posted by CVMichael
Title: VB6.0 – Sound and DirectXSound Tutorial
I thought you would cover non-Dx sound too.
Will you cover MIDI ? That's what I'm interested in. :)
I wish for a good (preferebly non-Dx) MIDI tutorial. But the way you started, I guess DirectX woun't be too hard. :thumb:
I want to build a software synthesizer that can save compositions as MIDI files.
P.S. Why that dummy file is there ? :D
-
Re: Sugestions or Comments about my Sound Tutorial
Sorry, I don't know anything about MIDI, so I won't cover it.
About the dummy file: vbforums.com will display the attached picture in the attachment section if there is only one picture attached. If there is more than one picture, it won't display any of them. This way i'm tricking it into not displaying the picture, because I don't want to display it there, I want to display the picture at the beginning of the post.
The non-DX sound, I mean wave files, creating and modifying sounds directly in the Byte (or Integer) arrays, as opposed to modify the sound in the DX buffer, or DX functions.
-
Re: Sugestions or Comments about my Sound Tutorial
It looks good so far. :)
You can put the image attachment in a post in the Support Images forum, and just link to it.
The only comment I have is the "Sound format: What is ..." section seems to run-on, I'd prefer to see it either as a list, or with each item (eg: Block Align) underlined and/or bold to make them stand out.
-
Re: Sugestions or Comments about my Sound Tutorial
Thanks...
OK... I'll do that (underlineing, and bold)
I also want to make some animated GIFs for the next section, but I'm having trouble finding a good and free GIF maker program.
http://www.vbforums.com/showthread.php?t=388956
I tried one (IrfanView 3.98) from download.com and I found the interface so difficult, I could not figure out how to even make a simple GIF, so I just un-installed it.
-
Re: Sugestions or Comments about my Sound Tutorial
I saw a post last week linking to a good simple one - but have no idea what it was called or which thread it was in tho :(
-
Re: Sugestions or Comments about my Sound Tutorial
"What is sound ?":
What about frequencies, and their representation as samples?
"Sound format":
Samplerate - I think you should also explain the Nyquist frequency.
"How to read or write to a wave file ?":
I thought those headers were called chunks.
Also your WaveReadFormat function may not work for all wavs,
there could also be other chunks (for example comments) before
the data chunk, or the data could be compressed, so the format
chunk could be much bigger.
I'm excited about the more advaned topics like tone recognition
and resampling. Will you also cover the FFT and digital filters (IIR, FIR)?
For the ACM encoder, I could give you a class I've written,
if you're interested.
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by rm_03
"What is sound ?":
What about frequencies, and their representation as samples?
I can explain about frequencies... but I'm not sure what you mean by "and their representation as samples"
Quote:
Originally Posted by rm_03
"Sound format":
Samplerate - I think you should also explain the Nyquist frequency.
I don't know anything about Nyquist frequency, I heared before about Nyquist theorem. But as I was saying don't know anything about it.
Maybe you can exaplain it, and I'll put it in the tutorial (giving credit to you for that part of course)
Quote:
Originally Posted by rm_03
"How to read or write to a wave file ?":
I thought those headers were called chunks.
Yea... I do have a "ChunkHeader" structure there...
Quote:
Originally Posted by rm_03
Also your WaveReadFormat function may not work for all wavs,
there could also be other chunks (for example comments) before
the data chunk, or the data could be compressed, so the format
chunk could be much bigger.
That's what this code does (From the WaveReadFormat):
VB Code:
' Ignore chunks until we get to the "data" chunk.
Get #InFileNum, , chunk
Do While chunk.lType <> &H61746164
For i = 1 To chunk.lLen
Get #InFileNum, , by
Next
Get #InFileNum, , chunk
Loop
Quote:
Originally Posted by rm_03
Will you also cover the FFT and digital filters (IIR, FIR)?
I was thinking to write something about FFT, but I have only little experience with it.
And I don't know about filters, but I'm excited to learn. And when I know something then i'll put it in the tutorial.
I was actually looking for a long time for code (or formulas) about digital filters, but I could not find anything usefull.
Quote:
Originally Posted by rm_03
For the ACM encoder, I could give you a class I've written,
if you're interested.
I saw you code already, not long before you posted it in the CodeBank, but one problem I found with it is that it does not convert in real time, you have to give it a wave file, and then it will convert to MP3.
I want to do this in real time, the code that I will explaing in the tutorial will be for both actually, for real time, and separate converting wave file to MP3 file.
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
I can explain about frequesncies... but I'm not sure what you mean by "and their representation as samples"
Basic stuff like how does a frequency at 10 Hz with the amplitude 16000 look like, and how to use sample points to create such a frequency.
Never heard of the "Nyquist theorem" ;), but the Nyquist frequency (the highest possible freq) would
be samplerate / 2, because you need at least 2 sample points for a frequency.
Quote:
That's what this code does (From the WaveReadFormat):
Oops, didn't see that, sorry :)
Quote:
I was actually looking for a long time for code (or formulas) about digital filters, but I could not find anything usefull.
Have you visited MusicDSP yet?
http://www.musicdsp.org/archive.php?classid=3
"RBJ Audio-EQ-Cookbook" is a good resource for various IIR filters.
I'd love to see that tutorial grow, there's nothing comparable to it in the VB world yet.
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by rm_03
Basic stuff like how does a frequency at 10 Hz with the amplitude 16000 look like, and how to use sample points to create such a frequency.
I was planing to show how to create tones of certain frequencyes, if you look at "My Objectives", You will see "How to dinamically create tones/beeps with custom frequencies."
I'm gonna put some images showing the wave data in that section of the tutorial.
Quote:
Originally Posted by rm_03
Never heard of the "Nyquist theorem" ;), but the Nyquist frequency (the highest possible freq) would
be samplerate / 2, because you need at least 2 sample points for a frequency.
Ow yea, that ring a bell :D
Yea, I think I'll explain it, but I have to read a little more about it, so that I can explain in words that actually make sence :)
Quote:
Originally Posted by rm_03
Nice !
I will definitelly spend some time checking the filters, and if I can get (at least one) of them to work, then I'll put that in the tutorial too.
Quote:
Originally Posted by rm_03
there's nothing comparable to it in the VB world yet.
What do you mean by that ?
You mean no one made a tutorial about sound in VB yet ? (I doubt that)
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
You mean no one made a tutorial about sound in VB yet ? (I doubt that)
At least I havn't seen anything for VB which deals with the lower level parts.
You just can't call "how to use MCI/WMP" a sound tutorial.
BTW, IIR filter for 16 bit:
in a module:
Code:
Option Explicit
Private Const Pi As Single = 3.14159265358979
Private Const LN2 As Single = 0.693147180559945
Public Enum IIR_TYPE
IIR_LOW_PASS
IIR_HIGH_PASS
IIR_BAND_PASS
IIR_NOTCH
IIR_PEAK_EQ
IIR_LOW_SHELVE
IIR_HIGH_SHELVE
End Enum
Public Function CreateBiquadIIR( _
ByVal iirtype As IIR_TYPE, _
ByVal dBGain As Single, _
ByVal freq As Single, _
ByVal srate As Single, _
ByVal bandwidth As Single _
) As IIRFilter
Dim A As Single, omega As Single
Dim sn As Single, cs As Single
Dim Alpha As Single, Beta As Single
Dim a0 As Single, a1 As Single, a2 As Single
Dim b0 As Single, b1 As Single, b2 As Single
Dim filter As IIRFilter
Set filter = New IIRFilter
A = 10 ^ (dBGain / 40)
omega = 2 * Pi * freq / srate
sn = Sin(omega)
cs = Cos(omega)
Alpha = sn * sinh(LN2 / 2 * bandwidth * omega / sn)
Beta = Sqr(A + A)
Select Case iirtype
Case IIR_LOW_PASS
b0 = (1 - cs) / 2
b1 = 1 - cs
b2 = (1 - cs) / 2
a0 = 1 + Alpha
a1 = -2 * cs
a2 = 1 - Alpha
Case IIR_HIGH_PASS
b0 = (1 + cs) / 2
b1 = -(1 + cs)
b2 = (1 + cs) / 2
a0 = 1 + Alpha
a1 = -2 * cs
a2 = 1 - Alpha
Case IIR_BAND_PASS
b0 = Alpha
b1 = 0
b2 = -Alpha
a0 = 1 + Alpha
a1 = -2 * cs
a2 = 1 - Alpha
Case IIR_NOTCH
b0 = 1
b1 = -2 * cs
b2 = 1
a0 = 1 + Alpha
a1 = -2 * cs
a2 = 1 - Alpha
Case IIR_PEAK_EQ
b0 = 1 + (Alpha * A)
b1 = -2 * cs
b2 = 1 - (Alpha * A)
a0 = 1 + (Alpha / A)
a1 = -2 * cs
a2 = 1 - (Alpha / A)
Case IIR_LOW_SHELVE
b0 = A * ((A + 1) - (A - 1) * cs + Beta * sn)
b1 = 2 * A * ((A - 1) - (A + 1) * cs)
b2 = A * ((A + 1) - (A - 1) * cs - Beta * sn)
a0 = (A + 1) + (A - 1) * cs + Beta * sn
a1 = -2 * ((A - 1) + (A + 1) * cs)
a2 = (A + 1) + (A - 1) * cs - Beta * sn
Case IIR_HIGH_SHELVE
b0 = A * ((A + 1) + (A - 1) * cs + Beta * sn)
b1 = -2 * A * ((A - 1) + (A + 1) * cs)
b2 = A * ((A + 1) + (A - 1) * cs - Beta * sn)
a0 = (A + 1) - (A - 1) * cs + Beta * sn
a1 = 2 * ((A - 1) - (A + 1) * cs)
a2 = (A + 1) - (A - 1) * cs - Beta * sn
End Select
filter.a0 = b0 / a0
filter.a1 = b1 / a0
filter.a2 = b2 / a0
filter.a3 = a1 / a0
filter.a4 = a2 / a0
filter.x1 = 0: filter.x2 = 0
filter.y1 = 0: filter.y2 = 0
Set CreateBiquadIIR = filter
End Function
Private Function sinh(angle As Single) As Single
sinh = (Exp(angle) - Exp(-angle)) / 2#
End Function
class "IIRFilter":
Code:
Option Explicit
' http://www.dspguru.com/sw/lib/biquad.c
Public a0 As Single
Public a1 As Single
Public a2 As Single
Public a3 As Single
Public a4 As Single
Public x1 As Single
Public x2 As Single
Public y1 As Single
Public y2 As Single
Public Sub ProcessSamples( _
intSamples() As Integer, _
ByVal datalen As Long _
)
Dim result As Single
Dim sample As Single
Dim i As Long
For i = 0 To datalen
sample = intSamples(i) / 32767
result = a0 * sample + a1 * x1 + a2 * x2 - a3 * y1 - a4 * y2
x2 = x1
x1 = sample
y2 = y1
y1 = result
If result > 1# Then
intSamples(i) = 32767
ElseIf result < -1# Then
intSamples(i) = -32768
Else
intSamples(i) = CInt(result * 32767)
End If
Next
End Sub
Usage:
Code:
Dim clsIIR as IIRFilter
Dim intSamples(44100 - 1) As Integer ' could be any size
Set clsIIR = CreateBiquadIIR(IIR_PEAK_EQ, 6, 170, 44100, 1)
clsIIR.ProcessSamples intSamples, UBound(intSamples)
Will boost your signal at 170 Hz by 6 dB with a bandwidth of 1 octave.
I love them :) Create some of them in a row and you got an equalizer.
-
Re: Sugestions or Comments about my Sound Tutorial
OMG !
I LOVE THAT...
I've been looking for an equalizer code for so long...
Where have you been till now ? :D
Though I have not tried it yet... owwww... I can't wait to have more free time ! to fool around with that code, and figure out how it works :)
I'm at work right now, and I'm busy at the moment. I hope I have time when I get home to look at it.
If you have more stuff like this, POST IT ! :D
-
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.
-
Re: Sugestions or Comments about my Sound Tutorial
I've seen a few "using sound in VB" type tutorials, but certainly nothing this complete - although I must admit I haven't looked particularly hard!
It looking to me as if your tutorial will become a must-bookmark page. :thumb:
-
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 :D
-
1 Attachment(s)
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).
Quote:
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.
-
Re: Sugestions or Comments about my Sound Tutorial
What do you guys think of the tutorial so far ?
(posting also to bump...)
-
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.
-
Re: Sugestions or Comments about my Sound Tutorial
That is becoming one huge thread!! It may be better if it was split across a few threads (Basic/Medium/Advanced?), with an Index thread to link them together - it's up to you tho, it's just a thought!
Another thing, instead of having the images uploaded into the thread itself, you can create a thread in the Support Images forum which contains them (as I do for the FAQs). You could also do this with the other attachments if you like.
-
Regarding the audio tutorial under construction
It seems the audio tutorial here contains the following error in the first WaveReadFormat() routine:
VB Code:
If header.lFormatLength < 16 Then Exit Function
header.lFormatLength holds 16 for either 8, 16 or 32 bits WAVE files.
The correct procedure would be to ask for the WaveFormat wBitsPerSample value, but we cannot simply "replace" it here since "Dim WaveFmt As WaveFormat" is declared in another different function named Create_Wave_File_Example(). (or, this lFormatLength might have nothing to do with the actual WAV bits and be a totally different parameter not explained in the tutorial)
Anyway, I have joined both WaveReadFormat and Create_Wave_File in one, in a function that simply retrieves True if the file is useable and False if not, and shows a messagebox when not. The function only let pass 16bit files, and I also use the WavDataStart variable to store the position of the actual WAV audio data start.
VB Code:
Public Function CheckWaveFile(ByVal sFileName As String) as Boolean
'Returns True if file is PCM WAVE and and 16-bit
Dim wHeader As FileHeader
Dim wFormat As WaveFormat
Dim wChunk As ChunkHeader
Dim lDataLength As Long
Dim wB as Byte
Dim wL as Long
WavNum = FreeFile
Open sFileName For Binary Access Read As #WavNum
Get #WavNum, 1, wHeader
If wHeader.lRiff <> &H46464952 Then GoTo InvalidFile ' Check for "RIFF" tag and exit if not found.
If wHeader.lWave <> &H45564157 Then GoTo InvalidFile ' Check for "WAVE" tag and exit if not found.
If wHeader.lFormat <> &H20746D66 Then GoTo InvalidFile ' Check for "fmt " tag and exit if not found.
Get #WavNum, , wFormat ' Retrieve format.
If wFormat.wBitsPerSample <> 16 Then GoTo InvalidFile ' check if file is 16-bit
' Seek to next chunk by discarding any format bytes.
For wL = 1 To wHeader.lFormatLength - 16
Get #WavNum, , wB
Next
' Ignore chunks until we get to the "data" chunk.
Get #WavNum, , wChunk
Do While wChunk.lType <> &H61746164
For wL = 1 To wChunk.lLen
Get #WavNum, , wB
Next
Get #WavNum, , wChunk
Loop
WavDataStart = LOF(WavNum) - wChunk.lLen + 1 'get position of audio data start
WavBytesPerSec = wFormat.nAvgBytesPerSec
WavBytesPerSample = (wFormat.wBitsPerSample / 8) * wFormat.nChannels
'Debug.Print "wav data start = " & WavDataStart
'Debug.Print "bytes per second = " & WavBytesPerSec
Close #WavNum
Exit Function
InvalidFile:
MsgBox "Failed to load selected wave file. Only 16-bit PCM WAV (uncompressed) files are supported.", vbCritical, App.ProductName
Close #WavNum
End Function
The tutorial so far is great and very clear, good work.
-
Re: Sugestions or Comments about my Sound Tutorial
Inuya5ha:
CVMichael has asked the comments/suggestions/etal be posted here so they are all in one place for him to look at. Therefore, I've merged the thread you posted in ClassicVb with this one.
Thanks for your feedback. :)
-
Re: Sugestions or Comments about my Sound Tutorial
Thanks for merging Hack.
Inuya5ha, the variable that returns how many bits the wave has is wFormat.wBitsPerSample.
So, to complete your function, put this line at the end of the function (Just before the "Exit Function" statement).
VB Code:
CheckWaveFile = wFormat.wBitsPerSample = 16
-
Re: Sugestions or Comments about my Sound Tutorial
Ow... I just noticed that you have the right code in the function:
VB Code:
If wFormat.wBitsPerSample <> 16 Then GoTo InvalidFile ' check if file is 16-bit
I don't understand what is the problem then ?
Why do you mention about header.lFormatLength, when you do have the right code ?
header.lFormatLength just returns the length of the structure, wich is always the same.
-
1 Attachment(s)
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.
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
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
Quote:
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 :)
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by rm_03
I have no clue what i'm seeing in that gif...
Quote:
Originally Posted by rm_03
Very nice stuff, hopefully this has some real time capabilities :)
Well, if in VB is not fast enough, it can always be converted to a C++ DLL, and used in VB like API... that will be fast for sure :)
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
I have no clue what i'm seeing in that gif...
X is frequency, Y is dB at that freq.
The blue line is perfect interpolation, how it should look like.
The green line is "no interpolation", and turns into a lot of audible distortion.
The pink line is linear interpolation, which already has a better quality.
The black line is cubic interpolation, and has the lowest distortion.
A perfect interpolation would be using sinc functions, I heard.
-
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.
-
Re: Sugestions or Comments about my Sound Tutorial
I have a question about your attached oscilloscope program
I understand as much as I can from the code but I could not understant where is the call to this function "DirectSoundRecord_GotWaveData"
It seems that we are calling this function after specific time...
where are we calling this function and how to change this specific time???
-
Re: Sugestions or Comments about my Sound Tutorial
GotWaveData is an event that comes from the DirectSound form (frmDX_Record.frm).
If you want to change the interval that event is called, you have to change the buffer size, and that is done in the Initialize function.
Look at the line in red:
VB Code:
If HalfBufferLen <= 0 Then
' make half of the buffer to be 100 ms
[COLOR=Red]HalfBuffLen = .lAvgBytesPerSec / 10[/COLOR]
Else
' using a "custom" size buffer
HalfBuffLen = HalfBufferLen
End If
From that line the program chooses how big the buffer is, therefore how often the GotWaveData is called.
-
Re: Sugestions or Comments about my Sound Tutorial
-
Re: Sugestions or Comments about my Sound Tutorial
I don't have time to read this whole thread but I do have some comments and suggestions.
I know you are trying to make it easier to understand for us DS noobs, but your split buffer tutorial can't even read all the wave files! Just 16 bit stereo I think. So you are gonna need to add some code to support all wavs like one of your tutorials have. Not to mention not have it load a wav whenever it finishes like it currently is doing. And unfortunately, your "support all wavs code" doesn't have a sample project, so I don't know what to do with it really. :(
I would also like you to add these tutorials:
- How to reverse the sounds so you can play it backwards.
- Allow more splits in the buffer
- Add special effects like chorus, flange, reverb, etc.
- How to equalize the sound.
- Play only the bass or treble portion of the sound.
- Changing the volumn of the buffer as well as the master volumn.
- How to crossfade.
- And we end the tutorial with a much more improved scratching program. :bigyello:
I also would like to see a DirectSound module engine with all the tools you need to manipulate, record, play, pause, stop, etc., sounds. Otherwise I'm gonna be borrowing code from your scratching prog to make one on my own. Messed up on the last one cause the sound was skipping or jumping a little bit.
-
How to adjust mic input level?
:wave: Hi CVMichael,
First let me say a big thank you for the exellent vb6 tone record and analyse app. It was very interesting and just what I was looking for.
I have adapted it and now have it all working and it is brilliant! :thumb:
I have one small problem left however, I need to adjust the mic record level in the vb6 app. My plan is to adjust the level until I get a good signal (i.e. I can analyse a tone which is being played and get the correct number).
I have looked at technet, etc. but cannot find anywhere how to adjust the mic level. Can you help please?
Many thanks
Steve
-
Re: How to adjust mic input level?
Quote:
Originally Posted by steve6375
I have one small problem left however, I need to adjust the mic record level in the vb6 app. My plan is to adjust the level until I get a good signal (i.e. I can analyse a tone which is being played and get the correct number).
Unfortunatelly, I don't know how to do that either, but if you do find code on how to change the rec volume, then I'm pretty sure I can figure out how to auto change to optimal level...
-
Re: Sugestions or Comments about my Sound Tutorial
Thanks for the reply.
I found this -http://www.codeguru.com/csharp/csharp/cs_graphics/sound/article.php/c10931/ but am not at all sure about translating it to vb6...
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by steve6375
Thanks for the reply.
I found this -http://www.codeguru.com/csharp/csharp/cs_graphics/sound/article.php/c10931/ but am not at all sure about translating it to vb6...
Actually, that does not help, but the link within it does: http://www.borg.com/~jglatt/tech/mixer.htm
But I don't have time to learn how to use the API's and make an application for this. Maybe if you find code using the APIs listed there ?
-
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.
-
Re: Sugestions or Comments about my Sound Tutorial
About Tone Recognition, see this code... Is simple and functional... Easy !
http://www.planet-source-code.com/vb...65667&lngWId=1
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by Robertovo
rm_03 already posted code for the Goertzel algorithm in this thread at post #18
And if you look at this thread http://www.vbforums.com/showthread.php?t=459138 at post #10, you will see I posted an application that will detect some frequencies
-
Re: Sugestions or Comments about my Sound Tutorial
It was a nice and good reference on recording sound mix source. but I have found a big bug in your recording source code. That is a runtime error if you record over 2 gbytes, it will show an error of a bad record number.
How can I solve this problem ? I saw that it is an vb automation error.
have a nice day .... and post your reply as soon as possible. plz...^^ :wave:
-
Re: Sugestions or Comments about my Sound Tutorial
Quote:
Originally Posted by windowbase
It was a nice and good reference on recording sound mix source. but I have found a big bug in your recording source code. That is a runtime error if you record over 2 gbytes, it will show an error of a bad record number.
How can I solve this problem ? I saw that it is an vb automation error.
have a nice day .... and post your reply as soon as possible. plz...^^ :wave:
Welcome to the forums :wave:
About your problem: I would be surprized if it didn't give you an error...
The program is made with VB functions. Internally VB keeps track of file position using a Long data type... A long data type has a maximum of 2^31=2,147,483,648 bytes... that's 2 GBytes.
If you want it to work with more than 2 GBytes, then change all the functions for file processing to API functions.
I don't want to change the code for file processing to API becuase the code is about sound processing, not file processing...
I never would have thought that anyone would record for that long anyways...
If you want to record for that long, then I think it is better to save it encoded to MP3 directly, you can record much longer like that.
For recording directly to MP3, take a look at this thread:
MP3 Encoder with Blade encoder
This project is not using API also, but because it's recording to MP3, you can record up to 37 hours (using encoding 128bps) for a 2 GByte file.
-
Re: Sugestions or Comments about my Sound Tutorial
Are you trying to create a file larger tha 2GB on A FAT32 volume? If so it won't work - you need an NTFS volume.
-
Re: Sugestions or Comments about my Sound Tutorial
Only 1,824 views and 41 ( now 42 ) replies since the 17th of this month. Why so unpopular?
-
Re: Sugestions or Comments about my Sound Tutorial
I guess not many people like to play with sound ?
-
Re: Sugestions or Comments about my Sound Tutorial
Thanks for this nice tutorial....
Before looking at your tutorial the things like "Wave File Format", Playing wave files and DirectX etc. were alien to me... Now I am very confident in using Directsound and playing streams of incoming PCM Audio data...
-
Re: Sugestions or Comments about my Sound Tutorial
Thank you, your welcome... too bad I never found time to finish it... (and when I had time, I forgot about it :p )
And welcome to the forums :wave:
-
Re: Sugestions or Comments about my Sound Tutorial
Hi Michael. It's been about a month since I downloaded Direct_Sound, so this is long overdue.
Great Job!
Yesterday, I read your tutorial. I won't pretend to understand all the code but it will become more apparent as I use and manipulate your code in my own projects. You deserve a ...
Big thumbs up!!!:thumb: :thumb: :thumb::thumb: :thumb: :thumb: :thumb: :thumb:
-
Re: Sugestions or Comments about my Sound Tutorial
Thank you CDRIVE, I'm glad it helped you.
I wish I had more time to write about all the things I know about sound, but my current job & life style does not give me enough free time for this.
-
Re: Sugestions or Comments about my Sound Tutorial
Hi CVMichael. Bless you for having gone to the trouble of sharing the intricacies of DirectSound programming with us all. I am well on the way to completing a project based on your explanations and example code, however am stuck on one little thing (well I hope it's little!). In your 'Simple DirectSound' example, you make this statement:
DsBuffer.SetCurrentPosition 0
'You can use the SetCurrentPosition to jump around a sound file as you like; which can be useful
I'd like a user to be able to select where to start sound play from. I'm hoping this can be accomplished via a slider on the form, the length of which always represents 100% of the sound length in the buffer, and wherever the slider knob is positioned, indicates to the user where in the sound duration the sound will start from. To do this, I would need to know how many bytes are in the buffer for the loaded sound, correct?
If so, can you please suggest what procedure, function to use to determine how many bytes are taken by the sound in the buffer, so that instead of Sound(Index).DSBuffer.SetCurrentPosition 0, I can specify Sound(Index).DSBuffer.SetCurrentPosition X, where X is the number of bytes equivalent to where the slider is positioned?
Thankyou so much
-
Re: Sugestions or Comments about my Sound Tutorial
Michael,
Love the tutorial. Thanks!
I am trying to make a "recording studio" on my PC for my son. I have recorded various sounds (.wav's) from my Yamaha key. What I want to do is create buttons that play them, and the ability to record what's been played. So...I will NOT be recording from an external device, but rather from the sounds that are already part of my app. Any quick tips on how to go about this? Does my question make sense?
Thanks!
Bryce
-
Re: Sugestions or Comments about my Sound Tutorial
Hi Bryce, welcome to the forums :wave:
Well, there are 3 ways to record that I can think of...
1) is to record the actions, for example, save in a file like this:
time difference from last action
what button was clicked
time difference from last action
what button was clicked
... and so on
When you play back,
wait for amount of time
simulate pressing the button
wait for amount of time
simulate pressing the button
... and so on
This method will create the smallest size of file possible. becuase you are saving only the actions done not the actual sounds.
2) Create the wave file as you go
Well, I don't know how you play the wave sounds right now, so my answer depends on that.
If you send me your project (you already know my e-mail), I can see what is the best way to do this.
3) The way I said before in the e-mail I sent you, simply record...
But I think you have the impression that recording can be done only from outside sources, and that is wrong.
All you have to do is tell Windows / sound card where to record FROM
You do this by going into your sound volume, and change to recording, then choose the source:
See this: http://www.vbforums.com/showpost.php...55&postcount=4
In your case you have to choose either "record master" or "wave"
-
Re: Sugestions or Comments about my Sound Tutorial
Michael,
Thanks for the reply.
You're right, I was a bit confused (your point #3). Thanks for clarifying that!
I really like your option #1, given the "light" nature of it. I'll give it a go.
Thanks again!
Bryce
-
Re: Sugestions or Comments about my Sound Tutorial
Hey CVMicheal! :wave:
I don't know if you are like this or not, but whenever I buy a new game or some kind of electronic device, I tend to read/skim the instruction manual (mainly look at the pictures) just to get a feel for what I'm getting involved with.
I have not read your tutorial... or even clicked the link yet. But I'm about to, and after reading this entire thread, I'm very excited to read the tutorial. :)
I'm an electrical engineering student currently starting my junior year and I can see alot of similarities in what I take in my classes (mainly math) and what I have seen in the code examples. I have a special project in mind where I need to detect sound frequencies from a microphone and I think I can actually do it... or at least get a better understanding with this tutorial.
So, just wanted to say hi and let you know that I am greatly looking forward to reading your tutorial. :)
Thanks in advance! Cheers!
- Zero
-
Re: Sugestions or Comments about my Sound Tutorial
Hi Zero, and welcome to the forums :wave:
Detecting frequencies is not covered in my tutorial, but there is code right here in this thread that can detect frequencies, thanks to rm_03.
You still need to know how to record sound to be able to do it, and that you can learn from my tutorial.
By the way guys, I forgot to say this before, I also posted my sound tutorial on CodeGuru, here:
http://www.codeguru.com/vb/gen/vb_mu...php/c15297__1/
-
Re: Sugestions or Comments about my Sound Tutorial
Michael,
I'm a bit rusty in VB (been "out of it" for a while now...). I'm having trouble recording the time an event (ie. button click takes place. If I use Now(), I don't seem to get enough precision if the clicks are close together (time doesn't change). Next I tried using a timer setting its interval to 1 and counting the milliseconds between clicks. When I wait two seconds between clicks, it only seems to have incremented to about 300 "counts" (would think it would be 2000?). I must be missing something obvious...
Also, would you happen to have any examples of code to do something like "create a .wav file with a one second long middle C...?"
Thanks for the assist!
Bryce
-
Re: Sugestions or Comments about my Sound Tutorial
You can use the Timer() to get a more precise value. It's precision is 1000 / 64 = 15.625 milliseconds
If you need even more precision than that, let me know
To create tones, see this:
http://www.vbforums.com/showthread.php?t=356482
-
Re: Sugestions or Comments about my Sound Tutorial
Although being new to sound engineering so to speak, I am not new to VB and I thought the tutorial was very kool, understandable and helped me quite a bit. I am working with a control from MultiMedia Softlabs Soind recorder and Sound Editor and so far it seems pretty easy to use, but your tutorial helped me to understand more of what it was doing under the covers. I would like to use this control and then your tutorial so that I could read the file in memory byte by byte to get the highest peak values (db level) so that I can normalize the file. If you know anything about this tool would be great.
-
Re: Sugestions or Comments about my Sound Tutorial
Michael,
I hesitate to post this, since I should be able to figure out the answer by looking through the code you've provided, but...
If I want to change the duration of a "note," what parm/variable in your example(s) would I use to do that? I get a bit confused when looking at "samples per second" and the other variables (ie. "Len")...
Also, do you have anything that shows what frequency each note on a "scale" would be?
Thanks again!
Bryce
-
Re: Sugestions or Comments about my Sound Tutorial
Actually I don't know what frequency belongs to what note, but searching on Google, i found this, and it looks pretty good:
http://www.lenardaudio.com/education/03_db.html
Yes, the Length parameter of GenerateTone function controls the length of the note/sound, but you need a buffer that can hold the length you give.
For example if your buffer is one second, and you pass the Length for 2 seconds, then of course it won't be able to generate a 2 second sound if the buffer is only one second.
The buffer should be as long as ALL the sounds you plan to generate.
Also, note that the Length parameter is in samples, so then you have to multiply your SamplesPerSec to the time you want to generate the note.
For example if your SamplesPerSec is 44100, and you want to generate a 2.5 second note, then the Length should be 44100 * 2.5 = 110250 (and the buffer should be equal or at least that)
-
Re: Sugestions or Comments about my Sound Tutorial
Michael,
Thanks once again!
Bryce
Also, the other thing I'm struggling a bit with is 1) generating the tone then 2) playing the tone back immediately (maybe not "immediately..." One button generates, another button plays...). I don't have any issues with generating, then saving, then finding the file I generated and playing it with Windows Media Player, for example, but when I try to play it from the same VB app in which I generate it, I'm not getting any playback.
That may be a little fuzzy, but any thoughts?