A simple-to-use sound file writer

A

Alf P. Steinbach

Just as a contribution, since someone hinted that I haven't really contributed
much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation since I
haven't yet discussed trig functions, and maybe /with/ changes suggested by you?

Module:


<code file="simple_sound.py">
"Lets you generate simple mono (single-channel) [.wav], [.aiff] or [.aifc] files."
import collections
import array
import math

DataFormat = collections.namedtuple( "DataFormat",
"open_func, append_int16_func"
)

default_sample_rate = 44100 # Usual CD quality.

def sample_square( freq, t ):
linear = freq*t % 1.0
if linear < 0.5:
return -1.0
else:
return 1.0

def sample_sawtooth( freq, t ):
linear = freq*t % 1.0
if linear < 0.5:
return 4.0*linear - 1.0
else:
return 3.0 - 4.0*linear

def sample_sine( freq, t ):
return math.sin( 2*math.pi*freq*t )

def _append_as_big_endian_int16_to( a, i ):
if i < 0:
i = i + 65536
assert( 0 <= i < 65536 )
a.append( i // 256 )
a.append( i % 256 )

def _append_as_little_endian_int16_to( a, i ):
if i < 0:
i = i + 65536
assert( 0 <= i < 65536 )
a.append( i % 256 )
a.append( i // 256 )

def aiff_format():
import aifc
return DataFormat( aifc.open, _append_as_big_endian_int16_to )

def wav_format():
import wave
return DataFormat( wave.open, _append_as_little_endian_int16_to )

class Writer:
"Writes normalized samples to a specified file or file-like object"
def __init__( self, filename, sample_rate = default_sample_rate,
data_format = aiff_format() ):
self._sample_rate = sample_rate
self._append_int16_func = data_format.append_int16_func
self._writer = data_format.open_func( filename, "w" )
self._writer.setnchannels( 1 )
self._writer.setsampwidth( 2 ) # 2 bytes = 16 bits
self._writer.setframerate( sample_rate )
self._samples = []

def sample_rate( self ):
return self._sample_rate

def write( self, normalized_sample ):
assert( -1 <= normalized_sample <= +1 )
self._samples.append( normalized_sample )

def close( self ):
data = array.array( "B" ) # B -> unsigned bytes.
append_int16_to = self._append_int16_func
for sample in self._samples:
level = round( 32767*sample )
append_int16_to( data, level )
self._writer.setnframes( len( self._samples ) )
self._writer.writeframes( data )
self._writer.close()
</code>


By the way, the reason that it holds on to data until 'close' and does the
writing there is to work around a bug in [wave.py]. That bug's now corrected but
wasn't when I wrote above. And possibly best to keep it like it is?

Ideally should deal with exceptions in 'close', calling close on the _writer,
but I haven't yet discussed exceptions in the hopefully-to-be book writings
where this probably will go.

Example usage, illustrating that it's simple to use (?):


<code file="aiff.py">
import simple_sound

sample_rate = simple_sound.default_sample_rate
total_time = 2
n_samples = sample_rate*total_time

writer = simple_sound.Writer( "ringtone.aiff" )
for i in range( n_samples ):
t = i/sample_rate
samples = (
simple_sound.sample_sine( 440, t ),
simple_sound.sample_sine( (5/4)*440, t ),
)
sample = sum( samples )/len( samples )
writer.write( sample )
writer.close()
</code>


Utility class that may be used to capture output (an instance of this or any
other file like class can be passed as "filename" to simple_sound.Writer):

<code>
class BytesCollector:
def __init__( self ):
self._bytes = array.array( "B" )
self._pos = 0

def raw_bytes( self ):
return self._bytes

def bytes_string( self ):
return self._bytes.tostring()

# File methods:

def tell( self ):
return self._pos

def seek( self, pos, anchor = 0 ):
assert( anchor == 0 ) # Others not supported
assert( pos <= len( self._bytes ) )
self._pos = pos

def write( self, bytes ):
pos = self._pos
if pos < len( self._bytes ):
s = slice( pos, pos + len( bytes ) )
self._bytes = bytes
self._pos = s.stop
else:
self._bytes.extend( bytes )
self._pos = len( self._bytes )

def flush( self ):
pass

def close( self ):
pass
</code>


Cheers & enjoy,

- Alf

PS: Comments welcome, except the BytesCollector which I just hacked together to
test something, it may contain eroRs but worked for my purpose.
 
S

Steve Holden

Alf said:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation
since I haven't yet discussed trig functions, and maybe /with/ changes
suggested by you?
I wouldn't hold back on the sine wave just because it would represent a
"forward reference". That's OK sometimes. Why not just put a comment in
to the effect that "The sine wave is created using a function from the
math module, which we'll be looking at in ..."?

Since the sine is the basis for all other waveforms its omission would
seem more than a little strange to anyone knowledgeable about audio, for
example.

regards
Steve
 
A

Alf P. Steinbach

* Steve Holden:
Alf said:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation
since I haven't yet discussed trig functions, and maybe /with/ changes
suggested by you?
I wouldn't hold back on the sine wave just because it would represent a
"forward reference". That's OK sometimes. Why not just put a comment in
to the effect that "The sine wave is created using a function from the
math module, which we'll be looking at in ..."?

Since the sine is the basis for all other waveforms its omission would
seem more than a little strange to anyone knowledgeable about audio, for
example.

I don't know very much if anything about audio. For example, in the code what I
called "sawtooth" wave is really "triangle" wave. The sawtooth is simpler, what
I called "linear" in the code.

And if you wonder, I was just checking the terminology now before starting to
write it up... Perhaps should have done that before posting code. But once I got
the idea of posting it I just posted it.

Anyway, as I recall any wave can be decomposed into sine waves, or square waves,
or almost whatever kind of waves. Think about a square wave of frequency f and
one of frequency 3f and perhaps third the amplitude (not sure), combined that's
already a good start on a sine wave. With some ugly staircasing but hey. And as
a matter of programming practicality, a triangle wave sounds almost like a sine
wave. It's just a little more edgy or "hairy", a slight buzz.



Cheers,

- Alf
 
S

Steve Holden

Alf said:
* Steve Holden:
Alf said:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation
since I haven't yet discussed trig functions, and maybe /with/ changes
suggested by you?
I wouldn't hold back on the sine wave just because it would represent a
"forward reference". That's OK sometimes. Why not just put a comment in
to the effect that "The sine wave is created using a function from the
math module, which we'll be looking at in ..."?

Since the sine is the basis for all other waveforms its omission would
seem more than a little strange to anyone knowledgeable about audio, for
example.

I don't know very much if anything about audio. For example, in the code
what I called "sawtooth" wave is really "triangle" wave. The sawtooth is
simpler, what I called "linear" in the code.

And if you wonder, I was just checking the terminology now before
starting to write it up... Perhaps should have done that before posting
code. But once I got the idea of posting it I just posted it.

Anyway, as I recall any wave can be decomposed into sine waves, or
square waves, or almost whatever kind of waves. Think about a square
wave of frequency f and one of frequency 3f and perhaps third the
amplitude (not sure), combined that's already a good start on a sine
wave. With some ugly staircasing but hey. And as a matter of programming
practicality, a triangle wave sounds almost like a sine wave. It's just
a little more edgy or "hairy", a slight buzz.
It's not clear to me that you can approximate any waveform with a
suitable combination of square waves, though I admit the idea has
intuitive appeal. But I know beyond a shadow of a doubt from my
education that any periodic function with a fundamental frequency f can
be approximated to whatever desired accuracy by the sum of sine and
cosine waves of frequencies Nf (N = 0, 1, 2, 3, ...) of appropriate
amplitudes (the frequency 0 component allows you to insert a "DC shift"
for waveforms that aren't symmetrical about zero). I seem to remember
the Fourier's theorem was the fundamental proof.

There is a very pretty discussion of all this, if you are mathematically
inclined, in

http://press.princeton.edu/books/maor/chapter_15.pdf

with a specific example for the sawtooth waveform.

I would definitely recommend renaming the waveforms you *do* use to
conform with accepted terminology. This will reduce reader confusion.

regards
Steve
 
A

Alf P. Steinbach

* Steve Holden:
Alf said:
* Steve Holden:
Alf P. Steinbach wrote:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation
since I haven't yet discussed trig functions, and maybe /with/ changes
suggested by you?

I wouldn't hold back on the sine wave just because it would represent a
"forward reference". That's OK sometimes. Why not just put a comment in
to the effect that "The sine wave is created using a function from the
math module, which we'll be looking at in ..."?

Since the sine is the basis for all other waveforms its omission would
seem more than a little strange to anyone knowledgeable about audio, for
example.
I don't know very much if anything about audio. For example, in the code
what I called "sawtooth" wave is really "triangle" wave. The sawtooth is
simpler, what I called "linear" in the code.

And if you wonder, I was just checking the terminology now before
starting to write it up... Perhaps should have done that before posting
code. But once I got the idea of posting it I just posted it.

Anyway, as I recall any wave can be decomposed into sine waves, or
square waves, or almost whatever kind of waves. Think about a square
wave of frequency f and one of frequency 3f and perhaps third the
amplitude (not sure), combined that's already a good start on a sine
wave. With some ugly staircasing but hey. And as a matter of programming
practicality, a triangle wave sounds almost like a sine wave. It's just
a little more edgy or "hairy", a slight buzz.
It's not clear to me that you can approximate any waveform with a
suitable combination of square waves,

Oh. It's simple to prove. At least conceptually! :)

Consider first that you need an infinite number of sine waves to create a
perfect square wave.

The opposite also holds: infinite number of square waves to create a perfect
sine wave (in a way sines and squares are opposites, the most incompatible).

With the goal of just a rough approximation you can go about it like this:

1. Divide a full cycle of the sine wave into n intervals. With
sine wave frequency f this corresponds to n*f sample rate for digital
representation.

2. Each interval will be approximated by a rectangular bar extending
up to or down to the sine wave. As it happens this (the bar's height) is
the sample value in a digital representation.

3. In the first half of the cycle, for each bar create that bar as
a square wave of frequency f, amplitude half the bar's height, and phase
starting at the bar's left, plus same square wave with negative sign
(inverted amplitude) and phase starting at the bar's right. And voilà,
not only this bar generated but also the corresponding other-way bar in
second half of cycle.

4. Sum all the square waves from step 3.

5. Let n go to infinity for utter perfectness! :)

And likewise for any other waveform.

After all, it's the basis of digital representation of sound!

though I admit the idea has
intuitive appeal. But I know beyond a shadow of a doubt from my
education that any periodic function with a fundamental frequency f can
be approximated to whatever desired accuracy by the sum of sine and
cosine waves of frequencies Nf (N = 0, 1, 2, 3, ...) of appropriate
amplitudes (the frequency 0 component allows you to insert a "DC shift"
for waveforms that aren't symmetrical about zero). I seem to remember
the Fourier's theorem was the fundamental proof.

Yes, the good Fourier had a thing for roundish curves. He saw them everywhere
and in anything. Eventually he found an infinite number of them in, to others,
invisible /sound/.

There is a very pretty discussion of all this, if you are mathematically
inclined, in

http://press.princeton.edu/books/maor/chapter_15.pdf

with a specific example for the sawtooth waveform.

I would definitely recommend renaming the waveforms you *do* use to
conform with accepted terminology. This will reduce reader confusion.

Yes, thanks.


Cheers,

- Alf
 
P

Peter Otten

Alf said:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation since
I haven't yet discussed trig functions, and maybe /with/ changes suggested
by you?
def _append_as_big_endian_int16_to( a, i ):
if i < 0:
i = i + 65536
assert( 0 <= i < 65536 )
a.append( i // 256 )
a.append( i % 256 )
data = array.array( "B" ) # B -> unsigned bytes.

Do you know that array.array() supports 16 bit signed integers? There's even
a byteswap() method to deal with endianess.
Utility class that may be used to capture output (an instance of this or
any other file like class can be passed as "filename" to
simple_sound.Writer):

<code>
class BytesCollector:

Are you reinventing io.BytesIO() here?

Peter
 
S

Steve Holden

Alf said:
* Steve Holden: [...]
With the goal of just a rough approximation you can go about it like this:

1. Divide a full cycle of the sine wave into n intervals. With
sine wave frequency f this corresponds to n*f sample rate for digital
representation.

2. Each interval will be approximated by a rectangular bar extending
up to or down to the sine wave. As it happens this (the bar's
height) is
the sample value in a digital representation.

3. In the first half of the cycle, for each bar create that bar as
a square wave of frequency f, amplitude half the bar's height, and
phase
starting at the bar's left, plus same square wave with negative sign
(inverted amplitude) and phase starting at the bar's right. And voilà,
not only this bar generated but also the corresponding other-way
bar in
second half of cycle.

4. Sum all the square waves from step 3.

5. Let n go to infinity for utter perfectness! :)

And likewise for any other waveform.

After all, it's the basis of digital representation of sound!
I'm sorry, but this is merely hand-waving. It looks appealing, but
there's no rigor there.

regards
Steve
 
M

Mel

Alf said:
* Steve Holden:

Oh. It's simple to prove. At least conceptually! :)

Consider first that you need an infinite number of sine waves to create a
perfect square wave.

The opposite also holds: infinite number of square waves to create a
perfect sine wave (in a way sines and squares are opposites, the most
incompatible).

No, it doesn't. The infinite set of sine waves that make a square wave
leave out the sine waves of frequency 2f, 4f, 6f, 8f, ... (2*n*f) ... .
Once you've left them out, you can never get them back. So sawtooth waves,
for example, can't generally be built out of sets of square waves.

You can inject even harmonics up to a given limit by adding "rectangular
waves" with given duty cycles, but the "given" part makes the math grubby.

Fourier transforms are cute to play with. If you don't care about run-time
there's:


#!/usr/bin/env python
# -*- coding: ASCII -*-
'''
$Id$'''
import math

def dft (sample):
'''Discrete Fourier Transform'''
n = len (sample)
n21 = n / 2 + 1
twopi = math.pi * 2.0
sin = math.sin
cos = math.cos
rex = [0]*n21
imx = [0]*n21
for k in xrange (n):
for i in xrange (n21):
a = twopi * k * i / n
rex += sin(a) * sample[k]
imx -= cos(a) * sample[k]
return rex, imx

#~ wave = [1]*32 + [-1]*32 # rectangular duty-cycle 1/2
#~ wave = [3]*16 + [-1]*48 # rectangular duty-cycle 1/4
wave = [7]*8 + [-1]*56 # rectangular duty-cycle 1/8
#~ wave = [15]*4 + [-1]*60 # rectangular duty-cycle 1/16
#~ wave = [31]*2 + [-1]*62 # rectangular duty-cycle 1/32
rex, imx = dft (wave)
print rex
print
print imx



The real coefficients show how the 8th, 16th, 24th, 32nd harmonics -- where
the coefficients are near zero -- have dropped out of the waveform.



Mel.
 
A

Alf P. Steinbach

* Mel:
No, it doesn't. The infinite set of sine waves that make a square wave
leave out the sine waves of frequency 2f, 4f, 6f, 8f, ... (2*n*f) ... .
Once you've left them out, you can never get them back. So sawtooth waves,
for example, can't generally be built out of sets of square waves.

The way to build a sine wave out of square waves is not a Fourier transform.

See the post you replied to for a simple procedure to build the sine wave.


Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Steve Holden:
Alf said:
* Steve Holden: [...]
With the goal of just a rough approximation you can go about it like this:

1. Divide a full cycle of the sine wave into n intervals. With
sine wave frequency f this corresponds to n*f sample rate for digital
representation.

2. Each interval will be approximated by a rectangular bar extending
up to or down to the sine wave. As it happens this (the bar's
height) is
the sample value in a digital representation.

3. In the first half of the cycle, for each bar create that bar as
a square wave of frequency f, amplitude half the bar's height, and
phase
starting at the bar's left, plus same square wave with negative sign
(inverted amplitude) and phase starting at the bar's right. And voilà,
not only this bar generated but also the corresponding other-way
bar in
second half of cycle.

4. Sum all the square waves from step 3.

5. Let n go to infinity for utter perfectness! :)

And likewise for any other waveform.

After all, it's the basis of digital representation of sound!
I'm sorry, but this is merely hand-waving. It looks appealing, but
there's no rigor there.

Bullshit.


Cheers,

- Alf
 
A

Alf P. Steinbach

* Peter Otten:
Alf said:
Just as a contribution, since someone hinted that I haven't really
contributed much to the Python community.

The [simple_sound] code will probably go into my ch 3 at <url:
http://tinyurl.com/programmingbookP3>, but sans sine wave generation since
I haven't yet discussed trig functions, and maybe /with/ changes suggested
by you?
def _append_as_big_endian_int16_to( a, i ):
if i < 0:
i = i + 65536
assert( 0 <= i < 65536 )
a.append( i // 256 )
a.append( i % 256 )
data = array.array( "B" ) # B -> unsigned bytes.

Do you know that array.array() supports 16 bit signed integers?

Yes. I used bytes since that seemed to be what [wave] required. But I tested now
and at least [aifc] handles 16-bit integers fine.

Hm, nice example down the drain...

There's even
a byteswap() method to deal with endianess.


Are you reinventing io.BytesIO() here?

Probably. :) Checking... Yes, I was; thanks!


Cheers,

- Alf
 
G

Grant Edwards

It's not clear to me that you can approximate any waveform
with a suitable combination of square waves,

Oh. It's simple to prove. At least conceptually! :)
[...]

With the goal of just a rough approximation you can go about
it like this:

1. Divide a full cycle of the sine wave into n intervals.
With sine wave frequency f this corresponds to n*f
sample rate for digital representation.

2. Each interval will be approximated by a rectangular bar
extending up to or down to the sine wave. As it happens
this (the bar's height) is the sample value in a digital
representation.

3. In the first half of the cycle, for each bar create that
bar as a square wave of frequency f, amplitude half the
bar's height, and phase starting at the bar's left, plus
same square wave with negative sign (inverted amplitude)
and phase starting at the bar's right. And voil?, not
only this bar generated but also the corresponding
other-way bar in second half of cycle.

4. Sum all the square waves from step 3.

5. Let n go to infinity for utter perfectness! :)

And likewise for any other waveform.

After all, it's the basis of digital representation of sound!

Huh? I've only studied basic DSP, but I've never heard/seen
that as the basis of digital represention of sound. I've also
never seen that representation used anywhere. Can you provide
any references?
 
A

Alf P. Steinbach

* Grant Edwards:
It's not clear to me that you can approximate any waveform
with a suitable combination of square waves,
Oh. It's simple to prove. At least conceptually! :)
[...]

With the goal of just a rough approximation you can go about
it like this:

1. Divide a full cycle of the sine wave into n intervals.
With sine wave frequency f this corresponds to n*f
sample rate for digital representation.

2. Each interval will be approximated by a rectangular bar
extending up to or down to the sine wave. As it happens
this (the bar's height) is the sample value in a digital
representation.

3. In the first half of the cycle, for each bar create that
bar as a square wave of frequency f, amplitude half the
bar's height, and phase starting at the bar's left, plus
same square wave with negative sign (inverted amplitude)
and phase starting at the bar's right. And voil?, not
only this bar generated but also the corresponding
other-way bar in second half of cycle.

4. Sum all the square waves from step 3.

5. Let n go to infinity for utter perfectness! :)

And likewise for any other waveform.

After all, it's the basis of digital representation of sound!

Huh? I've only studied basic DSP, but I've never heard/seen
that as the basis of digital represention of sound.

Oh, you have... The end result above (for finite n) is a sequence of sample
values of a sine wave. Ordinary digital representation of sound is exactly the
same, a sequence of sample values.

I've also never seen that representation used anywhere.

Yes, you have. A sequence of sample values is the representation used in any
direct wave file. Like [.wav] and, I believe, [.aiff].

Can you provide any references?

I don't have any references for the above procedure, it's sort of trivial.
Probably could find some references with an hour of googling. But no point.


Cheers & hth.,

- Alf


PS: To extend the above to a non-symmetric waveform, just first decompose that
waveform into sine waves (Fourier transform), then add up the square wave
representations of each sine wave. :)
 
S

Steve Holden

Grant said:
Huh? I've only studied basic DSP, but I've never heard/seen
that as the basis of digital represention of sound. I've also
never seen that representation used anywhere. Can you provide
any references?
Of course he can't. And it isn't the basis of analog quantization. And I
suspect Alf has never hear of Shannon's theorem.

But don't listen to me, apparently I'm full of it.

regards
Steve
 
A

Alf P. Steinbach

* Steve Holden:
Just for the record: Grant has seen that representation numerous times, he just
didn't recognize it.

Can you provide any references?
Of course he can't. And it isn't the basis of analog quantization.

Of course it isn't the basis of quantization: it *is* quantization, directly.

Which is the basis of digital representation.

And I suspect Alf has never hear of Shannon's theorem.

It's about 30 years since I did that stuff.

But don't listen to me, apparently I'm full of it.

You're spouting innuendo and personal attacks, repeatedly, so that seems to be
the case, yes. :)


Cheers,

- Alf
 
S

Steve Holden

Alf said:
* Steve Holden:

Just for the record: Grant has seen that representation numerous times,
he just didn't recognize it.



Of course it isn't the basis of quantization: it *is* quantization,
directly.
Nope, quantization is taking the *instantaneous value* of a waveform and
using that as the representation for one sample period. That is nowhere
near the same as summing periodic square waves.
Which is the basis of digital representation.
Well at least we agree that quantization is the basis of digital
representations. But I've never seen any summed square wave presentation
of it.
It's about 30 years since I did that stuff.
Well me too, but information theory is, after all, the theoretical
underpinning for the way I make my living, so I felt obliged to study it
fairly thoroughly.
You're spouting innuendo and personal attacks, repeatedly, so that seems
to be the case, yes. :)
Nothing personal about it. I'm just asking you to corroborate statements
you have made which, in my ignorance, I consider to be bogus hand-waving.

Nothing about you there. Just the information you are promoting. I don't
normally deal in innuendo and personal attacks. Though I do occasionally
get irritated by what I perceive to be hogwash. People who know me will
tell you, if I am wrong I will happily admit it.

regards
Steve
 
A

Alf P. Steinbach

* Steve Holden:
Alf said:
* Steve Holden:
Grant Edwards wrote:
[bogus hand-waving]
After all, it's the basis of digital representation of sound!
Huh? I've only studied basic DSP, but I've never heard/seen
that as the basis of digital represention of sound. I've also
never seen that representation used anywhere.
Just for the record: Grant has seen that representation numerous times,
he just didn't recognize it.

Can you provide any references?
Of course he can't. And it isn't the basis of analog quantization.
Of course it isn't the basis of quantization: it *is* quantization,
directly.
Nope, quantization is taking the *instantaneous value* of a waveform and
using that as the representation for one sample period. That is nowhere
near the same as summing periodic square waves.

There are two three things wrong with that paragraph. First, quantization can
not physically be instantaneous. So it's pretty much moot to try to restrict it
to that.

Second, for the mathematical exercise you can let the measurement be an
instantaneous value, that is, the value at a single point.

Third, the result of quantization is a sequence of values, each value present
for an interval of time, and the same is obtained by summing square waves.

I'm beginning to believe that you maybe didn't grok that simple procedure.

It's very very very trivial, so maybe you were looking for something more
intricate -- they used to say, in the old days, "hold on, this proof goes by
so fast you may not notice it!"

Well at least we agree that quantization is the basis of digital
representations. But I've never seen any summed square wave presentation
of it.

Well, I'm glad to be able to teach something.

Here's the MAIN IDEA in the earlier procedure: a square wave plus same wave
offset (phase) and negated, produces a set of more rectangular waveforms, which
I called "bars" -- in between the bars the two square waves cancel each other:

_
| |
| |
______| |______ ______
| |
| |
|_|

The bars alternate in positive and negative direction. They can be made as
narrow as you wish, and when they are as narrow as each sample interval then
each bar can represent the sample value residing in that interval. Even a sample
corresponding to a point measurement (if such were physically possible).

And samples are all that's required for representing the sine. And happily the
alternation of upgoing and downgoing bars is matched by an identical alternation
of the sine wave. :) Otherwise it would be a tad difficult to do this.

But then, representing sines is all that's required for representing any wave
form, since any wave form can be decomposed into sines.

Well me too, but information theory is, after all, the theoretical
underpinning for the way I make my living, so I felt obliged to study it
fairly thoroughly.
Nothing personal about it. I'm just asking you to corroborate statements
you have made which, in my ignorance, I consider to be bogus hand-waving.

OK.

May I then suggest going through the procedure I presented and *draw* the square
waves.

I dunno, but maybe that can help.

Nothing about you there. Just the information you are promoting. I don't
normally deal in innuendo and personal attacks. Though I do occasionally
get irritated by what I perceive to be hogwash. People who know me will
tell you, if I am wrong I will happily admit it.

There's a difference between an algorithm that you can implement, and hogwash.


Cheers,

- Alf
 
L

Lie Ryan

I'm beginning to believe that you maybe didn't grok that simple procedure.

It's very very very trivial, so maybe you were looking for something
more intricate -- they used to say, in the old days, "hold on, this
proof goes by so fast you may not notice it!"

Since you said it's trivial, then...
There's a difference between an algorithm that you can implement, and
hogwash.

please prove your claim by writing that algorithm in code and post it in
this list. The program must accept a .wav file (or sound format of your
choice) and process it according to your algorithm and the output
another .wav file (or sound format of your choice) that sounds roughly
similar to the input file.

PS: I have near-zero experience with sound processing
PPS: I will be equally delighted seeing either Steve admitting his wrong
or you admit your hogwash
PPPS: An alternative way to convince us is to provide a paper/article
that describes this algorithm.
PPPPS: Though I will be quite sad if you choose to reject the challenge
 
A

Alf P. Steinbach

* Lie Ryan:
Since you said it's trivial, then...

You can't get it more trivial.

please prove your claim by writing that algorithm in code and post it in
this list. The program must accept a .wav file (or sound format of your
choice) and process it according to your algorithm and the output
another .wav file (or sound format of your choice) that sounds roughly
similar to the input file.

First, the (very very trivial) algorithm I posted does *not* do that: by itself
it represents a sine wave, not an arbitrary wave form.

And second I'm not about to write Fourier transform code to satisfy someone who
refuses to do a milligram of thinking.

The Fourier part stuff needed to do what you're requesting is non-trivial, or at
least it's some work to write the code.

PS: I have near-zero experience with sound processing
PPS: I will be equally delighted seeing either Steve admitting his wrong
or you admit your hogwash
PPPS: An alternative way to convince us is to provide a paper/article
that describes this algorithm.
PPPPS: Though I will be quite sad if you choose to reject the challenge

I don't believe any of what you write here.



Cheers & hth.,

- Alf
 
A

Alf P. Steinbach

* Lie Ryan:
Since you said it's trivial, then...


please prove your claim by writing that algorithm in code and post it in
this list. The program must accept a .wav file (or sound format of your
choice) and process it according to your algorithm and the output
another .wav file (or sound format of your choice) that sounds roughly
similar to the input file.

In addition to my earlier reply (that the presented algorithm itself doesn't
generate arbitrary wave forms but only sines, i.e. that you're totally off the
mark),

your request is meaningless in another way, namely:

the algorithm does synthesis, which is easy (like computer speech), while you're
asking for analysis (like computer speech recognition), which is hard.

But maybe you're simply not able to understand the algorithm, trivial as it is.

So, a Python implementation (note, this program takes some time to run!):


<code filename="sinewave_from_squares.py">
# Generating a sine wave as a sum of square waves of various amplitudes & phases.
import simple_sound


# Step 1 "Divide a full cycle of the sine wave into n intervals."
n = 100


# Step 2 -- Just an explanation of the rest


# Step 3 "In the first half of the cycle, for each bar create that bar as
# a square wave of frequency f, amplitude half the bar's height, and phase
# starting at the bar's left, plus same square wave with negative sign
# (inverted amplitude) and phase starting at the bar's right."

square_waves = []
for i in range( n//2 ):
middle_of_interval = (i + 0.5)/n
amp = simple_sound.sample_sine( 1, middle_of_interval ) / 2
def first_square_wave( t, i = i, amp = amp ):
phase = i/n
return amp*simple_sound.sample_square( 1, t - phase )
def second_square_wave( t, i = i, amp = amp ):
phase = (i + 1)/n
return -amp*simple_sound.sample_square( 1, t - phase )
square_waves.append( first_square_wave )
square_waves.append( second_square_wave )


# Step 4 "Sum all the square waves from step 3."

def sample_squares( f, t ):
samples = []
o_time = f*t
for func in square_waves:
sq_sample = func( o_time )
samples.append( sq_sample )
return sum( samples )


# Finally, generate this is in a [.aiff] file so as to possibly satisfy Lie Rian:
if True:
f = 440
sample_rate = 44100
total_time = 2
n_samples = sample_rate*total_time

writer = simple_sound.Writer( "sinewave.aiff" )
for i in range( n_samples ):
t = 1*i/sample_rate
sample = sample_squares( f, t )
writer.write( sample )
writer.close()
</code>


Cheers & hth.,

- Alf
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,763
Messages
2,569,563
Members
45,039
Latest member
CasimiraVa

Latest Threads

Top