Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Categories

Welcome to the new platform of Programmer's Heaven! We apologize for the inconvenience caused, if you visited us from a broken link of the previous version. The main reason to move to a new platform is to provide more effective and collaborative experience to you all. Please feel free to experience the new platform and use its exciting features. Contact us for any issue that you need to get clarified. We are more than happy to help you.

Buffers in a wave recording application

YuIDFYuIDF Posts: 9Member
I need to write a basic application in which I choose a sound card and then records the input to a wav file. I need it to be done using the windows API (The MCI won't work for what I have in mind later).
My problems is how to manage the bffers in VB6... I need to prepare them for the device and than every time one of them fills up - switch buffers and move the info from the one that just finished to the output file. How can I do it?
Thanks a lot
Yuval
«1

Comments

  • JonathanJonathan Posts: 2,914Member
    : I need to write a basic application in which I choose a sound card and
    : then records the input to a wav file. I need it to be done using the
    : windows API (The MCI won't work for what I have in mind later).
    Given my experience of doing this kinda stuff in VB, I sure hope what you have in mind later doesn't involve a great deal of processing.

    : My problems is how to manage the bffers in VB6... I need to prepare them
    : for the device and than every time one of them fills up - switch buffers
    : and move the info from the one that just finished to the output file.
    : How can I do it?
    :
    How far have you got? I suggest that you make your buffers integer arrays (or byte arrays if you are doing 8-bit audio). You can declare a few of them, maybe even an array of arrays, and keep track of which one is the latest one to read data into and which one was the last one filled and ready to write to disk.

    You also will probably need to set up a callback function so you know when a buffer has been filled and is ready to be written to disk. Note that there are only certain things that you can do in the callback function, so be careful or you're going to end up with deadlock.

    You may also want to look to using the WriteFile API to write data to the file - it's already in a chunk of contiguous memory after all and I don't think VB lets you write an entire array to a file in one go. If it doesn't do internal buffering (I don't know that it does) then file I/O performance will really blow using VBs routines. Even if it does and you have to write individual values, that's a lot of function calls and that means overhead.

    If you run into any specific problems, let us know.

    Good luck,

    Jonathan

    ###
    for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");

  • BitByBit_ThorBitByBit_Thor Posts: 2,444Member
    : You may also want to look to using the WriteFile API to write data to the file - it's already in a chunk of contiguous memory after all and I don't think VB lets you write an entire array to a file in one go. If it doesn't do internal buffering (I don't know that it does) then file I/O performance will really blow using VBs routines. Even if it does and you have to write individual values, that's a lot of function calls and that means overhead.
    :
    : If you run into any specific problems, let us know.
    :
    : Good luck,
    :
    : Jonathan

    VB will let you dump the array to a file. You will have to make sure that the file is opened For Binary Access (My favorite!). If I am correct VB will write no Headers or extra info, only raw array data! (as long as you are using For Binary Access!)

    Greets...
    Richard

  • JonathanJonathan Posts: 2,914Member
    : VB will let you dump the array to a file.
    Can it? How?

    : You will have to make sure that the file is opened For Binary Access (My
    : favorite!). If I am correct VB will write no Headers or extra info, only
    : raw array data! (as long as you are using For Binary Access!)
    :
    Yep, which means you'd need to write a wave header. If you write data from byte 45, you've got space to add it in later when you know how much date you've got. (Sadly, I know that and didn't have to go and look it up...)

    Jonathan

    ###
    for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");

  • GenjuroGenjuro Posts: 913Member
    [b][red]This message was edited by Genjuro at 2004-8-14 14:18:30[/red][/b][hr]
    : : VB will let you dump the array to a file.
    : Can it? How?
    :
    : : You will have to make sure that the file is opened For Binary Access (My
    : : favorite!). If I am correct VB will write no Headers or extra info, only
    : : raw array data! (as long as you are using For Binary Access!)
    : :
    : Yep, which means you'd need to write a wave header. If you write data from byte 45, you've got space to add it in later when you know how much date you've got. (Sadly, I know that and didn't have to go and look it up...)
    :
    : Jonathan
    :
    : ###
    : for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    : (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    : /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");

    From MSDN:
    "If the variable being written is a [italic]dynamic[/italic] array, Put writes a descriptor whose length equals 2 plus 8 times the number of dimensions, that is, 2 + 8 * NumberOfDimensions."
    Otherwise it only writes the whole array, okay, but here's the problem: if you're recording, how are you going to pre-size the array in the source code?

    Anyways, MCI has functions to write .wav files. Now, even if it's not enough for what you're thinking to do, you can still use it only when you need it and make things a bit simpler when you can.
    As for managing audio buffers, check out DirectSound. If you're going to mix things in real time or such fancy things, or recording (DSound has recording APIs, too), it's your best bet IMO.




  • BitByBit_ThorBitByBit_Thor Posts: 2,444Member
    : From MSDN:
    : "If the variable being written is a [italic]dynamic[/italic] array, Put writes a descriptor whose length equals 2 plus 8 times the number of dimensions, that is, 2 + 8 * NumberOfDimensions."
    : Otherwise it only writes the whole array, okay, but here's the problem: if you're recording, how are you going to pre-size the array in the source code?
    :

    MSDN Also says:
    For files opened in Binary mode, all of the Random rules apply, except:

    - The Len clause in the Open statement has no effect. Put writes all variables to disk contiguously; that is, with no padding between records.


    - For any array other than an array in a user-defined type, Put writes only the data. No descriptor is written.


    - Put writes variable-length strings that are not elements of user-defined types without the 2-byte length descriptor. The number of bytes written equals the number of characters in the string. For example, the following statements write 10 bytes to file number 1:
    VarString$ = String$(10," ")
    Put #1,,VarString$


    Well, so you can easily write the buffer to file when you are using Binary mode!
    Greets...
    Richard

  • YuIDFYuIDF Posts: 9Member
    Hi!
    Thanks for the help. What I have decided to do is open a wave file - create an mmio file, add headers and then copying the data- whenever a buffer is filled, a message handler is called and copies gthe string from the buffer to the file.
    Now I need to do some actions no the string - analyze it a bit (my application should record only when the signal is of a certain power - so I guess I should be able to analyze tyhe buffer before I write it to file), and split a stero input to 2 mono files. I have understood that if you see the buffer as an array - than all the odd members are the right channel, and the even members are the left channel. how can you write a vb code that exploits it? I have understood that in VB you can't access strings like an array, and my buffers are strings. can I do it with strings? or should I be able to copy from the WAVEHDR.lpData to an array of short?
    THANKS A LOT
    Yuval
  • JonathanJonathan Posts: 2,914Member
    : Hi!
    : Thanks for the help. What I have decided to do is open a wave file -
    : create an mmio file, add headers and then copying the data- whenever
    : a buffer is filled, a message handler is called and copies gthe
    : string from the buffer to the file.
    : Now I need to do some actions no the string - analyze it a bit (my
    : application should record only when the signal is of a certain
    : power - so I guess I should be able to analyze tyhe buffer before I
    : write it to file), and split a stero input to 2 mono files. I have
    : understood that if you see the buffer as an array - than all the odd
    : members are the right channel, and the even members are the left
    : channel.
    Only if your array is base 0.

    : how can you write a vb code that exploits it? I have understood that
    : in VB you can't access strings like an array, and my buffers are
    : strings. can I do it with strings? or should I be able to copy from
    : the WAVEHDR.lpData to an array of short?
    :
    You're going to need to copy the data to an array if you want to manipulate it. In fact, there should be a way to pass a reference to the array to the WAVEHDR. Try something like:-

    Dim Buffer(1 to whatever) As Integer
    WAVEHDR.lpData = Buffer

    I think for that to work you'd have to declare the lpData As Any in the WAVEHDER type.

    Jonathan

    ###
    for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");

  • YuIDFYuIDF Posts: 9Member
    : : Hi!
    : : Thanks for the help. What I have decided to do is open a wave file -
    : : create an mmio file, add headers and then copying the data- whenever
    : : a buffer is filled, a message handler is called and copies gthe
    : : string from the buffer to the file.
    : : Now I need to do some actions no the string - analyze it a bit (my
    : : application should record only when the signal is of a certain
    : : power - so I guess I should be able to analyze tyhe buffer before I
    : : write it to file), and split a stero input to 2 mono files. I have
    : : understood that if you see the buffer as an array - than all the odd
    : : members are the right channel, and the even members are the left
    : : channel.
    : Only if your array is base 0.
    :
    : : how can you write a vb code that exploits it? I have understood that
    : : in VB you can't access strings like an array, and my buffers are
    : : strings. can I do it with strings? or should I be able to copy from
    : : the WAVEHDR.lpData to an array of short?
    : :
    : You're going to need to copy the data to an array if you want to manipulate it. In fact, there should be a way to pass a reference to the array to the WAVEHDR. Try something like:-
    :
    : Dim Buffer(1 to whatever) As Integer
    : WAVEHDR.lpData = Buffer
    :
    : I think for that to work you'd have to declare the lpData As Any in the WAVEHDER type.
    :
    : Jonathan
    :
    : ###
    : for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    : (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    : /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");
    :
    :
    So what I should do is - in the type declaration of WAVEHDR I should change lpData from long to variant, than I can make the assigment
    SomeWaveHDR= SomeArray instead of dynamically aloocating the buffer.
    (SomeArray(i) - an element of the array)
    then I couldnaccess the elements of SomeARRay by refrencing someWaveHDR.lpData(i).
    Did I get it right?
    Thanks


  • YuIDFYuIDF Posts: 9Member
    [b][red]This message was edited by YuIDF at 2004-8-16 5:50:46[/red][/b][hr]
    : : : Hi!
    : : : Thanks for the help. What I have decided to do is open a wave file -
    : : : create an mmio file, add headers and then copying the data- whenever
    : : : a buffer is filled, a message handler is called and copies gthe
    : : : string from the buffer to the file.
    : : : Now I need to do some actions no the string - analyze it a bit (my
    : : : application should record only when the signal is of a certain
    : : : power - so I guess I should be able to analyze tyhe buffer before I
    : : : write it to file), and split a stero input to 2 mono files. I have
    : : : understood that if you see the buffer as an array - than all the odd
    : : : members are the right channel, and the even members are the left
    : : : channel.
    : : Only if your array is base 0.
    : :
    : : : how can you write a vb code that exploits it? I have understood that
    : : : in VB you can't access strings like an array, and my buffers are
    : : : strings. can I do it with strings? or should I be able to copy from
    : : : the WAVEHDR.lpData to an array of short?
    : : :
    : : You're going to need to copy the data to an array if you want to manipulate it. In fact, there should be a way to pass a reference to the array to the WAVEHDR. Try something like:-
    : :
    : : Dim Buffer(1 to whatever) As Integer
    : : WAVEHDR.lpData = Buffer
    : :
    : : I think for that to work you'd have to declare the lpData As Any in the WAVEHDER type.
    : :
    : : Jonathan
    : :
    : : ###
    : : for(74,117,115,116){$::a.=chr};(($_.='qwertyui')&&
    : : (tr/yuiqwert/her anot/))for($::b);for($::c){$_.=$^X;
    : : /(p.{2}l)/;$_=$1}$::b=~/(..)$/;print("$::a$::b $::c hack$1.");
    : :
    : :
    : So what I should do is - in the type declaration of WAVEHDR I should change lpData from long to variant, than I can make the assigment
    : SomeWaveHDR= SomeArray instead of dynamically aloocating the buffer.
    : (SomeArray(i) - an element of the array)
    : then I couldnaccess the elements of SomeARRay by refrencing someWaveHDR.lpData(i).
    : Did I get it right?
    : Thanks
    :
    :
    I guess I dodn't get it right... when I try to prepare the header after making that assigment waveHdr.lpData = buffer
    (I ve declared: waveHdr As WAVEHDR, buffer(100) As Integer, and changed the type of lpData from Long to Variant))
    I get an error (invalid parameter passed to a system function, or something similiar) whane calling waveInPrepareHeader(...).
    What was my mistake?
    Thanks. you guys really save me...


  • GenjuroGenjuro Posts: 913Member
    : : : You're going to need to copy the data to an array if you want to manipulate it. In fact, there should be a way to pass a reference to the array to the WAVEHDR. Try something like:-
    : : : Dim Buffer(1 to whatever) As Integer
    : : : WAVEHDR.lpData = Buffer
    : : :
    : : : I think for that to work you'd have to declare the lpData As Any in the WAVEHDER type.
    : : :
    : : : Jonathan

    : : So what I should do is - in the type declaration of WAVEHDR I should change lpData from long to variant, than I can make the assigment

    : I guess I dodn't get it right... when I try to prepare the header after making that assigment waveHdr.lpData = buffer
    : (I ve declared: waveHdr As WAVEHDR, buffer(100) As Integer, and changed the type of lpData from Long to Variant))
    : I get an error (invalid parameter passed to a system function, or something similiar) whane calling waveInPrepareHeader(...).
    : What was my mistake?
    : Thanks. you guys really save me...

    To make a long story short I cut a few things.
    Jonathan suggested to declare the lpData member in the struct "As Any", not as a Variant, and it's probably a good idea.
    These are different data types; while Variant really means "any Basic type", Any means "I'll manage data myself in terms of raw memory, don't get in the way".

    I have to point out a thing, though.
    Declaring the array as an array of Integers will work fine for .wav whose sample size is 16 bits (except the sign bit will get in the way, as .wav samples are always unsigned... oh well), but what if the sample size is 8 or 32 bits?
    I once wrote a similar thing, and used plain strings, which I split into an array later, if I'm not wrong.
«1
Sign In or Register to comment.