/mysound

Simple sound generation and processing library for Python

Primary LanguagePython

mysound

Simple sound generation and processing library for Python

Why

The purpose of tht library is to have a simple to use library to create and process sound files.

Dedicated langages alredy exists, but I was not 100% satisfied with tools like cmusic or nyquist because they are too much oriented toward music production (is this real?) and the learning curve was steep.

Python already have a couple of libraries that somehow overlap mysound. But I was not too keen in requiring huge libraries installation like numpy and scipy just to generate sine wave or extract the envelope of a sound. Finally, a few other Python sound libraries alredy exists, but they are more inclined toward playing or recording sound--something outside of the primary goal of mysound

Least, and not last, A great motivation for that project was the fun factor!

How

I try to follow a gew guidelines while writing mysound:

  • imutability Most importantly, sound are stateless and immutable. There is no such thing as in-place transformations.
  • functionl design As far as I can, I try to stick a functional approach. Many parts of mysound are built around higher-order functions rather than OOP paradigme
  • speed is not a problem Well, this is self explanatory. I don't target real time processing nor even fast processing. mymusic is written 100% in Python based on the assumption it will be fast enougth for the kind of task I need
  • memory is not a problem Even if I try to not waste memory and chase memory leaks, on the other hand, I do not hesitate to keep samples--even intermediate processing result-- in main memory as long as they can still be accessible.
  • one size fits all Internally, all samples are stored and processed as double floating point numbers.

Key concepts

Channels

mysound is designed around the concept of channel. A channel is just a steam of samples encoded in floating point format (currently float 32). Channels are not tight to any parameter coming from their original source. So nothing prevents you from mixing channels from sources at different sampling rate but no automatic resampling will be performed. In the same spirit, you can easily achieve the chipmunk effect by just sending a stream to a sink using a higher sampling rate than the original stream source.

Some channels, like the silence channel, produce an infinite stream of samples. Other, notably those coming from an external source like a file, can only produce a finite number of samples. When there are no more samples to read, the stream is exhausted and subsequent readings from the channel will produce an empty list of samples.

Multichannels muxing and demuxing

Some objects inherently works with multiple channels at the same time. Take for example an interleaved stereo sound file. The library provides the demux to split a multichannel sources in a list of channels that can be independently handled.

Symmetrically, the library provides the mux function to create a multichannel object. Muxing is mostly useful for sinks that need to work with interleaved data.

Whereas single-channel sources produce an infinite steam of empty sample list when exhausted, multi-channel sources produce an infinite stream of the Python None constant to ease end-of-steam detection. A multi-channel stream is exhausted when at least one of its individual channels is exhausted.

Generators

A generator is a function that return a new channel. Generators can produce a new channel from an external source like a file), or using a computational method. silence or noise are examples of the later.

Note: Generators in mysound are concepts related to Python's generators, but they are implemented in a purely functional style, and not using the standard generators infrastructure (yield statements, and so on).

Generators should be idempotent. But this is sometimes hard to achieve, notably for generators based on random sources.

When a function create one (or several channels), based on already existing channel(s) we call it a processor rather than a generator

Processors

Processors are at the core of sound processing with mysound. A processor is a n-to-n function taking one or several channels and returning one or several channels. Processors are stateless and their output is fully defined by their input. As an example, the average processor (which can be used for stereo-to-mono conversion) will return a channel whose samples are the average of the input sample.

Sinks

Sinks are the counterpart of generators. They are function taking one or several input channels, and consuming the samples until at least one of the input stream is exhausted.

Actions

Thanks to the dynamic nature of Python, some actions can be performed independently to channels and multichannels. For example, the skip or trucate action used to discard sample. You may think of actions as higher-level utilities working similarly on 1-channel and multi-channel streams.