********************
Basic Manipulations
********************

AudioStream and Buffer objects have nearly all of their mathematical operators
overloaded.  It is easy to manipulate the data they contain.  Every operation
that can be done on a Buffer can be done on an AudioStream.  In the following
examples, only the Buffer case will be demonstrated, but it can easily be done
to an AudioStream as well.

Concatenation
-------------

After creating an empty Buffer, one can insert samples into it with
concatenation::

    import Nsound as ns
    b = ns.Buffer()
    b << 1 << 2 << 3

    print b.getLength()
    # 3
    print b.toList()
    # [1.0, 2.0, 3.0]

Buffers can be concatenated together::

    b2 = ns.Buffer()
    b2 << 6 << 7 << 8

    b << b2

    print b.getLength()
    # 6
    print b.toList()
    # [1.0, 2.0, 3.0, 6.0, 7.0, 8.0]

Scalar Math
-----------

When a scaler is applied to a Buffer or AudioStream, the scalar is applied
element-wise for all the samples contained in the Buffer::

    import Nsound as ns
    b = ns.Buffer()
    b << 1 << 2 << 3 << 6 << 7 << 8

    print b.toList()
    # [1.0, 2.0, 3.0, 6.0, 7.0, 8.0]

    b += 1.0            # b = b + 1.0 would also work
    print b.toList()
    # [2.0, 3.0, 6.0, 7.0, 8.0, 9.0]

    b *= 2.0
    print b.toList()
    # [4.0, 6.0, 12.0, 14.0, 16.0, 18.0]

    b /= 3.0
    print b.toList()
    # [1.3333, 2.0, 2.6666, 4.6666, 5.3333, 6.0]

Vector Math
-----------

Nsound also allows element-wise math between two Buffers.  Unlike other
packages such as Numpy or Matlab, the Buffers don't have to be the same length::

    import Nsound as ns

    b1 = ns.Buffer()
    b1 << 1 << 1 << 1

    b2 = ns.Buffer()
    b2 << 0 << 1 << 1 << 1

    # Addition

    b3 = b1 + b2

    print b3.toList()
    # [1.0, 2.0, 2.0]

    b3 = b2 + b1
    print b3
    # [1.0, 2.0, 2.0, 1.0]

    # Subtraction

    b3 = b1 - b2

    print b3.toList()
    # [1.0, 0.0, 0.0]

    b3 = b2 - b1

    print b3.toList()
    # [-1.0, 0.0, 0.0, 1.0]

    # Products

    b3 = b1 * b2

    print b3.toList()
    # [0.0, 1.0, 1.0]

    b3 = b2 * b1

    print b3.toList()
    # [0.0, 1.0, 1.0, 1.0]

    # Quotients

    b3 = b1 / b2

    print b3.toList()
    # [1e+20, 1.0, 1.0]

    b3 = b2 / b1

    print b3.toList()
    # [0.0, 1.0, 1.0, 1.0]