0
0

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.
[code:wczsr22d]
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)
[/code:wczsr22d]

The callback function
[code:wczsr22d]
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

End Function
[/code:wczsr22d]

Bit shift function
[code:wczsr22d]
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

End Function

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
Next
alPow2(31) = &H80000000
End If
‘ return
Pow2 = alPow2(Exponent)
End Select

End Function
[/code:wczsr22d]

  • You must to post comments
0
0

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….

  • You must to post comments
0
0

[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.

  • You must to post comments
0
0

😀 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.

  • You must to post comments
0
0

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.

  • You must to post comments
0
0

DSP callbacks work fine for me in native code.

  • You must to post comments
0
0

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. vilo999@pobox.sk

  • You must to post comments
0
0

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.

  • You must to post comments
0
0

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? :roll:

  • You must to post comments
0
0

thats an interesting idea, multithreading would be a good solution. If you can figure out how to do it than it would be great!! I havent looked at the article but it seems promising.

  • You must to post comments
Showing 9 results
Your Answer

Please first to submit.