Re: Sugestions or Comments about my Sound Tutorial
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...^^
Welcome to the forums
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.
Last edited by CVMichael; Sep 16th, 2007 at 08:56 PM.
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?
Make as many mistakes as you can as quickly as you can. We want to make sure that we make a great enough number of mistakes in a given amount of time so that we can be successful.
"Persistence is the magic of success." Paramahansa Yogananda
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
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!!!
<--- Did someone help you? Please rate their post. The little green squares make us feel really smart!
If topic has been resolved, please pull down the Thread Tools & mark it Resolved.
Is VB consuming your life, and is that a bad thing??
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?
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?
Re: Sugestions or Comments about my Sound Tutorial
Hi Bryce, welcome to the forums
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
Re: Sugestions or Comments about my Sound Tutorial
Hey CVMicheal!
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.
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...?"
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?
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)
Last edited by CVMichael; Oct 17th, 2008 at 07:59 AM.
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.
Re: Sugestions or Comments about my Sound Tutorial
Michael,
I've attached some (crude) code via which I am trying to generate 7 notes, each of which is .25 seconds long (11025/44100). When I play the sounds back, they are indeed .25 seconds long, but each file itself still plays for 2 seconds. Can you tell me where/how I'm creating this phenomenom?
Re: Sugestions or Comments about my Sound Tutorial
CVMichael,
Thanks again for your tutes. I am using your subs to accomplish the following things:
1. load a wav file into an array
2. process the sound data in the array with various DSP routines, such as reverse, filter, distort etc
3. load the processed array in a sound buffer
4. play the sound
5. enable the 'usual' abilities of changing frequency and volume of the sound in the buffer.
Trouble is, everything is working upto 4. However, trying to do either of the following on the buffer:
Re: Sugestions or Comments about my Sound Tutorial
Please post the code in the post not as attachment, because I am at work and the firewall here blocks attachments.
You just have to encapsulate your code with [HIGHLIGHT="vbcode"]your code here[/HIGHLIGHT] tags.
The answer is in my tutorial if one looked hard enough , You are probably missing this:
vbcode Code:
' allow frequency changes and volume changes
BuffDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLVOLUME
If you have other flags in there, remember you have to use "Or" or "+" to mix flags.
Also, read the lFlags documentation because not all flags can be mixed with one another
Re: Sugestions or Comments about my Sound Tutorial
I do have:
BuffDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLVOLUME in the code
Code is attached.
Simply create a form with two command buttons: CmdLoad, CmdPlay, and two text boxes: Text1, Text2, and one check box: Check1
Copy the code into the form, set a reference to DirectX8 For Visual Basic Type Library. Under Sub Form_Load, Text2 is loaded with the path to a wav file. Change path to suit - I've been loading 8 bit mono files. Now when you press CmdLoad, the wav file in Text2 is loaded and the datalength of the file is shown in Text1. If you tick the checkbox before pressing CmdLoad, the wav file is reversed then loaded. Pressing CmdPlay plays the load in the buffer. All good.
Now problem is that if if you uncomment either of the DSSecBuffer.SetFrequency 11000 or DSSecBuffer.SetVolume -1500 under CmdPlay_Click, the error is thrown.
Regards,
DocNash
vbcode Code:
Option Explicit
Private Type FileHeader
lRiff As Long
lFileSize As Long
lWave As Long
lFormat As Long
lFormatLength As Long
End Type
Private Type WaveFormat
wFormatTag As Integer
nChannels As Integer
nSamplesPerSec As Long
nAvgBytesPerSec As Long
nBlockAlign As Integer
wBitsPerSample As Integer
End Type
Private Type ChunkHeader
lType As Long
lLen As Long
End Type
Private DX As New DirectX8
Private DSEnum As DirectSoundEnum8
Private DIS As DirectSound8
Dim DSSecBuffer As DirectSoundSecondaryBuffer8
Dim WaveData() As Byte
Dim RevAr()
Dim WaveFmt As WaveFormat
Dim DataLength As Long
Private Sub CmdLoad_Click()
Dim BuffDesc As DSBUFFERDESC
Set DSEnum = DX.GetDSEnum
Set DIS = DX.DirectSoundCreate(DSEnum.GetGuid(1))
DIS.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL
BuffDesc.lFlags = DSBCAPS_CTRLFREQUENCY Or DSBCAPS_CTRLVOLUME
Set DSSecBuffer = CreateSoundBufferFromFile(Text2.Text, BuffDesc)
Re: Sugestions or Comments about my Sound Tutorial
Two Questions in One if you please:
1. Is there any way to specify upto where the sound in the buffer should play TO, similar to the way one can specify where it should start play FROM thusly:
Sound(Index).DSBuffer.SetCurrentPosition X?
The reason I ask, is that it would seem the only way to constrain the TO is in the creation of the buffer itself using:
BuffDesc.lBufferBytes = X
2. Let us say I have WaveData() filled with 8 bit sound. Would the following be appropriate to
a) make it signed
b) cast into the range -1 to +1 (so I can apply signal processing algorithms to the sound which require the input to be in that range)
c) write back to WaveData() as unsigned 8-bit again:
(PS this works, but I am not sure whether the approach is mathematically correct in dealing with +127 to -128):
dim K as Long
dim Sample as Long
dim r as Single
dim f as Single
For K = LBound(WaveData) to UBound(WaveData)
r = (WaveData(K) - 127) / 127
f = Apply Signal Processing(r)
Sample = (CLng(f * 127)) + 127
WaveData(K) = Sample
Next K
Re: Sugestions or Comments about my Sound Tutorial
1) Your question does not make sense, maybe you should say why you want to do it like this ?
Why can't you just put in the buffer what you want to play, instead of putting everything (i guess), then stop it at a certain point ?
2) What you did is correct...
Just a note:
You don't have to PM me on a thread where I am posting already, because any new reply in threads where I am subscribed show up in my "User CP".
If you make a NEW thread, and you want me to reply, then send me a PM with the link so I am aware of your thread, but if I already posted in that thread then I am aware as soon as you post (as soon as I log-in), you don't have to send PM...
Last edited by CVMichael; Dec 10th, 2008 at 04:19 PM.
Re: Sugestions or Comments about my Sound Tutorial
CVMichael,
Thanks for your validation of 2).
Re 1) the context is I'm building a sampling drum machine, with extensive sound editing options for each instrument sample, such as add the sample to synthesized waves, or AM or FM the sample with synthesized waves, filter, add effects or dynamically (while the pattern is playing) specify via sliders the start and end points of the sound. It is to satisfy this latter requirement that I'm asking the question.
In other words, enablement of real-time 'segment' manipulation of the sound in each channel while the rhythm loop is playing is what I'm aiming for. It's all about 'zero-latency tactility'.
So, envision a horizontal slider bar with a 'start handle' and a 'stop handle' that can be independently moved on the bar - the sound snipet that plays is what's between the handles.
It'd be neat then if the start and stop handles set something like this:
Sound(Index).DSBuffer.SetStartPosition X
Sound(Index).DSBuffer.SetEndPosition Y
Just wanted to validate that DirectSound doesn't offer anything like the above, and that the only option I've got is for first handle to do this:
Sound(Index).DSBuffer.SetCurrentPosition X
and the second handle to do this:
BuffDesc.lBufferBytes = X
where X is a subset of DataLength, and the buffer is loaded anew each time the second handle is moved...
Re: Sugestions or Comments about my Sound Tutorial
CVMichael,
Thanks for the suggestion. Attached is the code core I'm using. A form with a textbox Text1 (simply shows the wav file being loaded), CmdLoad button, CmdPlay button, and the following sliders: HscrollVol, HscrollFreq, HscrollPlayFrom, HscrollPlayTo.
The code core has been working fine. Then I added to it to be able to do the 'stop play event' processing. What I added is shown suffixed by '****
Am now getting a runtime error 430 'Class does not support automation or does not support expected interface' on the DSSecBuffer.SetNotificationPositions line (and it doesn't matter whether the line is under the HScrollPlayTo_Change event, or under the CmdLoad event - which I've commented out)
Any advice would be greatly appreciated.
Regards,
DocNash
vbcode Code:
Option Explicit
Private Type FileHeader
lRiff As Long
lFileSize As Long
lWave As Long
lFormat As Long
lFormatLength As Long
End Type
Private Type WaveFormat
wFormatTag As Integer
nChannels As Integer
nSamplesPerSec As Long
nAvgBytesPerSec As Long
nBlockAlign As Integer
wBitsPerSample As Integer
End Type
Private Type ChunkHeader
lType As Long
lLen As Long
End Type
Private DX As New DirectX8
Private DSEnum As DirectSoundEnum8
Private DIS As DirectSound8
Dim DSSecBuffer As DirectSoundSecondaryBuffer8
Private EventsNotify(0) As DSBPOSITIONNOTIFY '*****
Private StopEvent As Long '*****
Implements DirectXEvent8 '*****
Dim WaveData() As Byte
Dim WaveFmt As WaveFormat
Dim DataLength As Long
Private Sub CmdLoad_Click()
Dim BuffDesc As DSBUFFERDESC
Set DSEnum = DX.GetDSEnum
Set DIS = DX.DirectSoundCreate(DSEnum.GetGuid(1))
DIS.SetCooperativeLevel Me.hWnd, DSSCL_NORMAL
Set DSSecBuffer = CreateSoundBufferFromFile(Text1.Text, BuffDesc)
Re: Sugestions or Comments about my Sound Tutorial
CVMichael,
Yep, it needed the DSBCAPS_CTRLPOSITIONNOTIFY.
Also, looks like the sound DOES need to be stopped before removing and re-creating the event. If I do DSSecBuffer.Stop before destroying and re-creating event, everything works fine, but if I comment out that line, a runtime 'Automation error' gets thrown at the DSSecBuffer.SetNotificationPositions line.
I am astounded not only by your prodigious knowledge of directsound (what was your motivation/incentive to gain this comprehensive know-how by the way?), but also your willingness to share your experience AND to top it all off, your responsiveness to questions and issues.
Re: Sugestions or Comments about my Sound Tutorial
A few years ago, I plaied with sound quite a lot. I made a few applications that used sound, the best one I made was a voice chat application, but it was not just a 1 to 1 conversation, anyone in the chat room could talk at the same time, therefore I had to mix sounds. Also because I had to send the sound over the internet I had to encode the sound "on the fly", and send it, and do the reverse on the receiving side.
I learned a lot by making that application (even though I did not finish it).
If you search on the forums, you will see I tried to do quite a few things with sound, like this tone recognition, for example.
There was a time (when I was in school) that I had a whole lot of free time to play & discover, but not anymore.
Regarding your question, I did not have to re-create events in the sound buffer before, that's why I was not sure if it will work, but apparently it did
After you work with it for so long, you have a fealing of the possibilities and problems you might encounter, even though you did not actually did it before.
It feels good/gratifying to help someone/anyone, if I did not have my full time job, I would do this more often, but latelly I rarelly have free time. If you look back in this thread you will see a few questions that I left unanswered, that's because I was too busy at that time...
Last edited by CVMichael; Dec 18th, 2008 at 09:32 AM.