instead of depending on data = array('h') .. write samples 1 by 1 tow = wave.open("wav.wav", "w")

Discussion in 'Python' started by '2+, Jul 28, 2009.

  1. '2+

    '2+ Guest

    it says
    Wave_write.writeframes(data)
    will that mean
    "from array import array"
    is a must?

    this does the job:

    import oil
    import wave
    from array import array

    a = oil.Sa()

    w = wave.open("current.wav", "w")
    w.setnchannels(2)
    w.setsampwidth(2)
    w.setframerate(44100)

    data = array('h')

    for gas in range(44100 * 5):
    a.breath()
    r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    data.append(r)
    data.append(l)

    w.writeframes(data.tostring())
    w.close()

    don't like array becoming so huge so tested this and it was also okay:

    for gas in range(44100 * 5):
    a.breath()
    data = array('h')
    r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    data.append(r)
    data.append(l)
    w.writeframes(data.tostring())

    but without array .. it becomes 15secs(3 times longer than was
    intended to be) of wav file:

    for gas in range(44100 * 5):
    a.breath()
    r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    w.writeframes(hex(r))
    w.writeframes(hex(l))

    should i just be happy with depennding on using array?
    or is there a solution to make the last one work properly?

    tia

    --
    SaRiGaMa's Oil Vending Orchestra
    is podcasting:
    http://sarigama.namaste.jp/podcast/rss.xml
    and supplying oil.py for free:
    http://oilpy.blogspot.com/
     
    '2+, Jul 28, 2009
    #1
    1. Advertising

  2. '2+

    Peter Otten Guest

    Re: instead of depending on data = array('h') .. write samples 1 by 1 to w = wave.open("wav.wav", "w")

    '2+ wrote:

    > it says
    > Wave_write.writeframes(data)
    > will that mean
    > "from array import array"
    > is a must?
    >
    > this does the job:
    >
    > import oil
    > import wave
    > from array import array
    >
    > a = oil.Sa()
    >
    > w = wave.open("current.wav", "w")
    > w.setnchannels(2)
    > w.setsampwidth(2)
    > w.setframerate(44100)
    >
    > data = array('h')
    >
    > for gas in range(44100 * 5):
    > a.breath()
    > r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    > l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    > data.append(r)
    > data.append(l)
    >
    > w.writeframes(data.tostring())
    > w.close()
    >
    > don't like array becoming so huge so tested this and it was also okay:
    >
    > for gas in range(44100 * 5):
    > a.breath()
    > data = array('h')
    > r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    > l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    > data.append(r)
    > data.append(l)
    > w.writeframes(data.tostring())
    >
    > but without array .. it becomes 15secs(3 times longer than was
    > intended to be) of wav file:
    >
    > for gas in range(44100 * 5):
    > a.breath()
    > r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    > l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    > w.writeframes(hex(r))
    > w.writeframes(hex(l))


    Doesn't it sound strange, too? You are writing bogus bytes to the file.
    Compare:

    >>> import array
    >>> array.array("h", [42]).tostring()

    '*\x00'
    >>> hex(42)

    '0x2a'

    Not only do they differ in length, the contents are different, too. If
    you're unfamiliar with string escape codes, here's a way to see the bytes:

    >>> map(ord, array.array("h", [42]).tostring())

    [42, 0]
    >>> map(ord, hex(42))

    [48, 120, 50, 97]

    > should i just be happy with depennding on using array?
    > or is there a solution to make the last one work properly?


    There is a way to make the last one work: use struct.pack("h", r) instead of
    hex(r). I'm of course assuming that the first version does give you the
    desired result. You should not continue before you have verified that.

    I still recommend array for performance reasons. If memory usage is an issue
    you can adopt a hybrid approach:

    # untested
    from itertools import islice
    from array import array

    def gen_data():
    for gas in xrange(44100 * 5): # range --> xrange
    a.breath()
    r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    yield r
    yield l

    data = gen_data()
    N = 2**20
    while True:
    chunk = array('h')
    chunk.extend(islice(data, N))
    if not chunk:
    break
    w.writeframes(chunk.tostring())

    This will limit the array size to 4N bytes.

    Peter
     
    Peter Otten, Jul 29, 2009
    #2
    1. Advertising

  3. '2+

    '2+ Guest

    Re: instead of depending on data = array('h') .. write samples 1 by 1to w = wave.open("wav.wav", "w")

    o wow .. there's still a lot to learn ..
    okay .. if i get stucked with the memory usage issue
    will try this hybrid .. thanx for the example!!

    it took about 40 min to render 1min of wav
    so i'll just keep this project like 15 sec oriented
    and maybe that'll keep me away from the mem trouble

    and my oil.py is still so cheap..
    sad thing is that "the result sound strange" is true to
    all versions :s

    thanx again anyway!


    On Wed, Jul 29, 2009 at 5:21 PM, Peter Otten<> wrote:
    > '2+ wrote:
    >
    >> it says
    >> Wave_write.writeframes(data)
    >> will that mean
    >> "from array import array"
    >> is a must?
    >>
    >> this does the job:
    >>
    >> import oil
    >> import wave
    >> from array import array
    >>
    >> a = oil.Sa()
    >>
    >> w = wave.open("current.wav", "w")
    >> w.setnchannels(2)
    >> w.setsampwidth(2)
    >> w.setframerate(44100)
    >>
    >> data = array('h')
    >>
    >> for gas in range(44100 * 5):
    >>     a.breath()
    >>     r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    >>     l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    >>     data.append(r)
    >>     data.append(l)
    >>
    >> w.writeframes(data.tostring())
    >> w.close()
    >>
    >> don't like array becoming so huge so tested this and it was also okay:
    >>
    >> for gas in range(44100 * 5):
    >>     a.breath()
    >>     data = array('h')
    >>     r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    >>     l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    >>     data.append(r)
    >>     data.append(l)
    >>     w.writeframes(data.tostring())
    >>
    >> but without array .. it becomes 15secs(3 times longer than was
    >> intended to be) of wav file:
    >>
    >> for gas in range(44100 * 5):
    >>     a.breath()
    >>     r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    >>     l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    >>     w.writeframes(hex(r))
    >>     w.writeframes(hex(l))

    >
    > Doesn't it sound strange, too? You are writing bogus bytes to the file.
    > Compare:
    >
    >>>> import array
    >>>> array.array("h", [42]).tostring()

    > '*\x00'
    >>>> hex(42)

    > '0x2a'
    >
    > Not only do they differ in length, the contents are different, too. If
    > you're unfamiliar with string escape codes, here's a way to see the bytes:
    >
    >>>> map(ord, array.array("h", [42]).tostring())

    > [42, 0]
    >>>> map(ord, hex(42))

    > [48, 120, 50, 97]
    >
    >> should i just be happy with depennding on using array?
    >> or is there a solution to make the last one work properly?

    >
    > There is a way to make the last one work: use struct.pack("h", r) instead of
    > hex(r). I'm of course assuming that the first version does give you the
    > desired result. You should not continue before you have verified that.
    >
    > I still recommend array for performance reasons. If memory usage is an issue
    > you can adopt a hybrid approach:
    >
    > # untested
    > from itertools import islice
    > from array import array
    >
    > def gen_data():
    >    for gas in xrange(44100 * 5): # range --> xrange
    >        a.breath()
    >        r = int(32767 * (a.pulse(1) + a.pulse(2) + a.pulse(3)) / 3.0)
    >        l = int(32767 * (a.pulse(4) + a.pulse(5) + a.pulse(6)) / 3.0)
    >        yield r
    >        yield l
    >
    > data = gen_data()
    > N = 2**20
    > while True:
    >    chunk = array('h')
    >    chunk.extend(islice(data, N))
    >    if not chunk:
    >        break
    >    w.writeframes(chunk.tostring())
    >
    > This will limit the array size to 4N bytes.
    >
    > Peter
    >
    > --
    > http://mail.python.org/mailman/listinfo/python-list
    >




    --
    SaRiGaMa's Oil Vending Orchestra
    is podcasting:
    http://sarigama.namaste.jp/podcast/rss.xml
    and supplying oil.py for free:
    http://oilpy.blogspot.com/
     
    '2+, Jul 29, 2009
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. chenggf
    Replies:
    1
    Views:
    405
    avnrao
    May 25, 2004
  2. red floyd
    Replies:
    5
    Views:
    1,053
    Nathan Wijnia
    Jun 21, 2007
  3. Karthik
    Replies:
    0
    Views:
    805
    Karthik
    Sep 5, 2007
  4. rara10
    Replies:
    0
    Views:
    949
    rara10
    Jan 30, 2009
  5. Shiva
    Replies:
    2
    Views:
    1,655
    Chris Maryan
    Feb 2, 2009
Loading...

Share This Page