I’ve translated the echo callback from Bretts example into VB, but I’m having problems with it. Sometimes it will work but other times it crashes with this error message:
[quote:wczsr22d]The instruction at “0x02f11530” referenced memory at “0x001ff000”. The memory could not be “read”[/quote:wczsr22d]
I’m using a bit shifting function that I found on the internet that is supposed to be faster by using lookup tables and which prevents overflows. I know it has something to do with the bit shifting but I dont know how to fix it. Could somebody look at the code and tell me where my flaw is?
Initializing fmod, variables, buffers, etc.
InitVal = FSOUND_Init(44100, 8, FSOUND_INIT_GLOBALFOCUS)
Stream = FSOUND_Stream_Open("C:\Documents and Settings\All Users\Documents\My Music\d_rain_down.mp3", FSOUND_16BITS + FSOUND_STEREO, 0, 0)
EchoLen = MaxEchoLen
EchoOffset = 0
EchoBuff = GlobalAlloc(&H40 Or &H0, FSOUND_DSP_GetBufferLength * 4)
EchoUnit = FSOUND_DSP_Create(AddressOf EchoCallback, FSOUND_DSP_DEFAULTPRIORITY_USER, 0)
Channel = FSOUND_Stream_Play(FSOUND_FREE, Stream)
Call FSOUND_DSP_SetActive(EchoUnit, 1)
The callback function
Public Function EchoCallback(ByVal newbuffer As Long, ByVal origbuffer As Long, ByVal Length As Long, ByVal param As Long) As Long
Dim mixertype As Long Dim taillen As Long Dim startlen As Long mixertype = FSOUND_GetMixer() 'Must be 16bit stereo integer buffer.. sorry blendmode (32bit) and fpu (32bit float) dont support this. If (mixertype = FSOUND_MIXER_BLENDMODE Or mixertype = FSOUND_MIXER_QUALITY_FPU) Then EchoCallback = newbuffer End If 'Echobuff is a ringbuffer that we copy the mixbuffer to. 'If the length of the write exceeds the end of the echo buffer, 'then do the mix in 2 parts, the end part, and the start part. If (EchoOffset + Length > EchoLen) Then taillen = EchoLen - EchoOffset startlen = Length - taillen 'Feedback history from echo buffer into mixbuffer Call FSOUND_DSP_MixBuffers(newbuffer, EchoBuff + ShiftLeft(EchoOffset, 2), taillen, OutputFreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO Or FSOUND_16BITS) Call FSOUND_DSP_MixBuffers(newbuffer + ShiftLeft(taillen, 2), EchoBuff, startlen, OutputFreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO Or FSOUND_16BITS) 'Now copy result into echo buffer again for next time Call CopyMemory(ByVal EchoBuff + ShiftLeft(EchoOffset, 2), ByVal newbuffer, taillen * 4) Call CopyMemory(ByVal EchoBuff, ByVal newbuffer + ShiftLeft(taillen, 2), startlen * 4) Else 'No wrapping echo buffer write, just do a straight write 'Feedback history from echo buffer into mixbuffer Call FSOUND_DSP_MixBuffers(newbuffer, EchoBuff + ShiftLeft(EchoOffset, 2), Length, OutputFreq, 128, FSOUND_STEREOPAN, FSOUND_STEREO Or FSOUND_16BITS) 'Now copy result into echo buffer again for next time Call CopyMemory(ByVal EchoBuff + ShiftLeft(EchoOffset, 2), ByVal newbuffer, Length * 4) End If EchoOffset = EchoOffset + Length If (EchoOffset >= EchoLen) Then EchoOffset = EchoOffset - EchoLen End If 'Echo history has been mixed into new buffer, so return it. EchoCallback = newbuffer
Bit shift function
Public Function ShiftLeft(ByVal Value As Long, ByVal times As Long) As Long
‘ we need to create a mask of 1’s corresponding to the
‘ times in VALUE that will be retained in the result
Dim mask As Long, signBit As Long
' return zero if too many times If times >= 32 Then Exit Function ' return the value if zero times If times = 0 Then ShiftLeft = Value: Exit Function ' this extracts the bit in Value that will become the sign bit mask = Pow2(31 - times) ' this calculates the sign bit of the result signBit = CBool(Value And mask) And &H80000000 ' this clears all the most significant times, ' that would be lost anyway, and also clears the sign bit Value = Value And (mask - 1) ' do the shift to the left, without risking an overflow ' and then add the sign bit ShiftLeft = (Value * Pow2(times)) Or signBit
Public Static Function Pow2(ByVal Exponent As Long) As Long
Dim alPow2(0 To 31) As Long
Dim i As Long
Select Case Exponent
Case 0 To 31
‘ initialize lookup table
If alPow2(0) = 0 Then
alPow2(0) = 1
For i = 1 To 30
alPow2(i) = alPow2(i – 1) * 2
alPow2(31) = &H80000000
Pow2 = alPow2(Exponent)
- Paranoid_Android asked 13 years ago
[quote="brett":1mh1jsix]man thats a complicated lot of code just for a shift.. why dont you just change x << 2 to x * 4?[/quote:1mh1jsix]
That’s actually what I had originally but I got a lot of problems with it overflowing, which is why I found this code that supposedly prevents overflows.
😀 Ok! Thanks for your help Brett, I found where my error was! It was something stupid that I should have recognized earlier. Anyways, I’m converting all of the other DSP examples from C into VB if anyone wants to use them in their projects.
You can download my echo example [url=http://members.aol.com/libertyed1986/vbecho.zip:32p6uej7]here[/url:32p6uej7]. Just put an mp3 into the folder you save it to called test.mp3.
Anyway how do you make the exe’s of your programs? Are you running them only from ide? Ide works in something like P-Code, when the app is compiled in p-code it works. Isnt there a way to compile to native code with dsp callbacks? I wanted to use dsp callbacks too but unfortunately my app doesnt work properly in p-code…. Isnt there some way of starting vb dsp echo thread safely in native code? Thanks.
Thats strange… Even if i compile your vbecho project to native code it will crash. Like all others with callbacks in new thread. The callback function wont even be called, the exe will crash immediately after creating the dsp thread (same like the CreateThread API). Could you please post me your compiled vbecho project so i can see the differences? I use VB6 SP5. firstname.lastname@example.org
Hmmm, this is weird. You are right. Except, my cd ripper app, that uses a DSP callback, works fine in native code, but I just tried my echo example in native code and it crashed. This is strange, why would it crash for some apps and work fine for others?? Maybe brett has an explanation.
I think that it is not Fmod’s error. This is an vb compiler issue. It may be the same as CreateThread api in vb. When you call FSOUND_DSP_SetActive(echounit, 1) fmod will launch a new thread, right? So my idea is: start a new thread using this article: [url:duayu1l9]http://www.Planet-Source-Code.com/vb/scripts/ShowCode.asp?txtCodeId=26900&lngWId=1[/url:duayu1l9] eg. create an object within the callback and THEN activate the unit, so vb wont crash… But, how to do this?
I have been playing with it but i think that it is not possible. Firstly, the createwin32thread function asks for an object in the first parameter. modDSP is not a valid one. Second, if echocallback would be placed in frmmain, then we miss addressof echocallback, and then the dsp unit can not be created. Third, the multithreaded function takes only one parameter. So the only way left is using a c++ dll….
Please login first to submit.