-
Use of RtlMoveMemory
after a night of head scratching I think it's time to ask the experts
I've got a sample of a wave player using the Win API called "PlayWave" (from
Microsoft)
I've added a Bandpass filter to this which works a treat for analysing it,
but I wanted a way to preview the
Bandpassed audio. As the play routine uses the wave data held in memory I
thought I can just write the
processed data back to the memory where I got the original data.
I reversed the calling method of RtlMoveMemory to get these declares
<
Declare Sub CopyStructFromPtr Lib "kernel32" Alias "RtlMoveMemory" (struct
As Any, ByVal ptr As Long, ByVal cb As Long)
Declare Sub CopyPtrFromStruct Lib "kernel32" Alias "RtlMoveMemory" (ByVal
ptr As Long, struct As Any, ByVal cb As Long)
>
then reversed the Get function to create a Put function
<
Sub Get16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByRef Vol
As Double)
Dim sample16 As Integer
Dim ptr As Long
ptr = sample * format.nBlockAlign + bufferIn
CopyStructFromPtr sample16, ptr + (2 * nChannel), 2
Vol = sample16 / 32768
End Sub
Sub Put16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByVal Vol
As Double)
Dim sample16 As Integer
Dim ptr As Long
sample16 = Vol * 32768
ptr = sample * format.nBlockAlign + bufferIn
CopyPtrFromStruct ptr + (2 * nChannel), sample16, 2
End Sub
>
the wave is read into memory like this (I'm pretty sure this allows
read/write from what I've read)
<
' Allocate soundbuffer and read sound data
GlobalFree hmem
hmem = GlobalAlloc(&H40, mmckinfoSubchunkIn.ckSize)
bufferIn = GlobalLock(hmem)
rc = mmioRead(hmmioIn, bufferIn, mmckinfoSubchunkIn.ckSize)
>
The bandpass processes okay, but the wave file playback remains the same, so
I'm assuming it's
my Put16BitSample function that is wrong. I tried different ways to pass
the data, but to no avail.
Any helpers ?
MTIA
cheers
Geoff
p.s. Bandpass code available if anyone's interested.
-
Re: Use of RtlMoveMemory
Hi Geoff,
I'm not sure if this will *solve* your probem, but I have found (through
experience ;-) that using RtlMoveMemory becomes harder rather than easier
when you declare it all different ways to try to keep some kind of "type
safety". Don't get me wrong. Many people including Dan Appleman and even
Microsoft (anthropomorphically speaking) advocate this approach. I even use
this method in many of my samples on my site since I have been learning as I
go (as we all do).
However, it is wrong ;-) It works, but it is unnecessarily complicated.
K.E.P. finally convinced me of this about 1 year ago in these very
newsgroups<g>...
> I reversed the calling method of RtlMoveMemory to get these declares
> <
> Declare Sub CopyStructFromPtr Lib "kernel32" Alias "RtlMoveMemory" (struct
> As Any, ByVal ptr As Long, ByVal cb As Long)
> Declare Sub CopyPtrFromStruct Lib "kernel32" Alias "RtlMoveMemory" (ByVal
> ptr As Long, struct As Any, ByVal cb As Long)
Just declare it like this:
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src
As Any, ByVal len As Long)
Now you have a flexible declare and you specify how it is used *in your
code* - e.g.,
> Sub Get16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByRef Vol
> As Double)
>
> Dim sample16 As Integer
> Dim ptr As Long
>
> ptr = sample * format.nBlockAlign + bufferIn
First you need to verify that this (ptr) is really a pointer. If it is
then you pass it ByVal and CopyMemory copies directly from the numerical
address specified in the ptr variable. Since sample16 is a variable and not
a pointer to a variable you pass it ByRef and CopyMemory copies the data
"pointed to" by ptr into the variable. Make sense?;
Call CopyMemory( sample16, ByVal ptr + (2 * nChannel), 2)
> Vol = sample16 / 32768
>
> End Sub
You put ByVals where you are specifying an address (pointer) and you put
ByRefs where you are specifying variables to fill or copy from (then VB
passes a pointer to the variable for you). Making sense yet?
> Sub Put16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByVal Vol
> As Double)
>
> Dim sample16 As Integer
> Dim ptr As Long
>
> sample16 = Vol * 32768
> ptr = sample * format.nBlockAlign + bufferIn
Call CopyMemory( ByVal ptr + (2 * nChannel), sample16, 2 )
>
> End Sub
> >
>
I didn't take the time to go through the MS sample (though I know the one
you are talking about and it's pretty convoluted ;-) so maybe my changes
above won't work "as is". I'm just hoping they might shed a spark of light
on what RtlCopyMemory is doing - since that is what it seems you wanted
most.
> cheers
>
> Geoff
>
> p.s. Bandpass code available if anyone's interested.
I would love to see this code.
Best regards,
Ray Mercer
www.shrinkwrapvb.com
-
Re: Use of RtlMoveMemory
Hi Geoff,
I'm not sure if this will *solve* your probem, but I have found (through
experience ;-) that using RtlMoveMemory becomes harder rather than easier
when you declare it all different ways to try to keep some kind of "type
safety". Don't get me wrong. Many people including Dan Appleman and even
Microsoft (anthropomorphically speaking) advocate this approach. I even use
this method in many of my samples on my site since I have been learning as I
go (as we all do).
However, it is wrong ;-) It works, but it is unnecessarily complicated.
K.E.P. finally convinced me of this about 1 year ago in these very
newsgroups<g>...
> I reversed the calling method of RtlMoveMemory to get these declares
> <
> Declare Sub CopyStructFromPtr Lib "kernel32" Alias "RtlMoveMemory" (struct
> As Any, ByVal ptr As Long, ByVal cb As Long)
> Declare Sub CopyPtrFromStruct Lib "kernel32" Alias "RtlMoveMemory" (ByVal
> ptr As Long, struct As Any, ByVal cb As Long)
Just declare it like this:
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dst As Any, src
As Any, ByVal len As Long)
Now you have a flexible declare and you specify how it is used *in your
code* - e.g.,
> Sub Get16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByRef Vol
> As Double)
>
> Dim sample16 As Integer
> Dim ptr As Long
>
> ptr = sample * format.nBlockAlign + bufferIn
First you need to verify that this (ptr) is really a pointer. If it is
then you pass it ByVal and CopyMemory copies directly from the numerical
address specified in the ptr variable. Since sample16 is a variable and not
a pointer to a variable you pass it ByRef and CopyMemory copies the data
"pointed to" by ptr into the variable. Make sense?;
Call CopyMemory( sample16, ByVal ptr + (2 * nChannel), 2)
> Vol = sample16 / 32768
>
> End Sub
You put ByVals where you are specifying an address (pointer) and you put
ByRefs where you are specifying variables to fill or copy from (then VB
passes a pointer to the variable for you). Making sense yet?
> Sub Put16BitSample(ByVal sample As Long, ByVal nChannel As Long, ByVal Vol
> As Double)
>
> Dim sample16 As Integer
> Dim ptr As Long
>
> sample16 = Vol * 32768
> ptr = sample * format.nBlockAlign + bufferIn
Call CopyMemory( ByVal ptr + (2 * nChannel), sample16, 2 )
>
> End Sub
> >
>
I didn't take the time to go through the MS sample (though I know the one
you are talking about and it's pretty convoluted ;-) so maybe my changes
above won't work "as is". I'm just hoping they might shed a spark of light
on what RtlCopyMemory is doing - since that is what it seems you wanted
most.
> cheers
>
> Geoff
>
> p.s. Bandpass code available if anyone's interested.
I would love to see this code.
Best regards,
Ray Mercer
www.shrinkwrapvb.com
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
Forum Rules
|
Top DevX Stories
Easy Web Services with SQL Server 2005 HTTP Endpoints
JavaOne 2005: Java Platform Roadmap Focuses on Ease of Development, Sun Focuses on the "Free" in F.O.S.S.
Wed Yourself to UML with the Power of Associations
Microsoft to Add AJAX Capabilities to ASP.NET
IBM's Cloudscape Versus MySQL
|
Bookmarks