Skip to content

Latest commit

 

History

History
908 lines (696 loc) · 32.8 KB

File metadata and controls

908 lines (696 loc) · 32.8 KB

2011

2011-04 April

2011-04-19 Tuesday

fixing the scaling of the fft magnitude

The original was: complexarray = ((((Complex( Signal.newFrom( magarray[0] ), Signal.newFrom( magarray[1] ) ).magnitude.reverse)).log10) * 80).clip(0, 255);

This resulted in magnitude values below 1 producing negative values after log10, which were then clipped away.

Correction attempt (needs more testing after re setting fft buffer size to 1024)

this clipped the higher frequencies away at fft buffer size 2048 or more, but the same was for the original algorithm

complexarray = ( (Complex(Signal.newFrom(magarray[0]), Signal.newFrom(magarray[1])).magnitude.reverse + 1).log10

  • 80

).clip(0, 255);

minimum necessary change:
complexarray = ((((Complex( Signal.newFrom( magarray[0] ), Signal.newFrom( magarray[1] ) ).magnitude.reverse) + 1).log10) * 80).clip(0, 255);
Debug tries:

complexarray = Complex( Signal.newFrom( magarray[0] ), Signal.newFrom( magarray[1] ) ).magnitude.reverse + 1; // prevent items < 0 producing negative values at log10

[“min, max before log10”, complexarray.minItem, complexarray.maxItem].postln; complexarray = complexarray.log10; [“min, max after log10”, complexarray.minItem, complexarray.maxItem].postln; complexarray = complexarray * 160; [“max after * 160”, complexarray.maxItem].postln;

complexarray = complexarray.clip(0, 255); [“max after clip”, complexarray.maxItem].postln;

/* complexarray = (80 * Complex( Signal.newFrom( magarray[0] ), Signal.newFrom( magarray[1] ) ).magnitude.reverse.log10).clip(0, 255); */

Introduce more color gradations and tweak the accessing of these

use: classvar <>defaultFFTBufSize = 1024, <>colorSize = 64;

recalcGradient { var colors;

// colors = (0..16).collect({ | val | blend(background, color, val / 16)}); // THIS: colors = (0..colorSize).collect({ | val | blend(background, color, val / colorSize)}); // colors = (1..64).pow(0.01).normalize.collect(blend(background, color, _)); colints = colors.collect({ | col | Image colorToPixel: col }); }

futhermore:

the intensity multiplier variable and the multiplication by 80 need to be tweaked.
The colors could be graded with a bias for low values as follows:

colors = (1..colorSize).pow(0.01).normalize.collect(blend(background, color, _));

Better solution (introduces much more detail in low energy regions
  • Note taken on [2011-04-19 Tue 18:26]

The power exponent in calcGradient could be reduced to 0.1 or other values

recalcGradient

recalcGradient { var colors; colors = (1..colorSize).pow(0.01).normalize.collect(blend(background, color, _)); colints = colors.collect({ | col | Image colorToPixel: col }); }

spectrum magnitude scaling in startruntask

complexarray = log10( 1 + Complex( Signal.newFrom(magarray[0]), Signal.newFrom(magarray[1]) ).magnitude.reverse; ).clip(0, 1) * intensity;

complexarray.do({ | val, i | fftDataArray[i] = colints.clipAt((val * colorSize).round); });

added scaleable exponent for color mapping

Default: 0.5. Tested between: 0.01 and 1 Higher values: peaks show clearer, lower magnitudes may disappear Lower values: peaks smear more, lower magnitudes are displayed

is var windowparent necessary? perhaps window is enough

2011-04-20 Wednesday

simplify additional process mechanism using dependants vars

Define vars in Spectrogram2:

  1. imageObjects: objects that draw on the image (before it is sent to pen)
  2. penObjects: objects that draw with pen (after image is sent to pen)

An object that wants to draw, must add itself to one of those two lists. Spectrogram2 will send all objects stored in imageObects the message drawImage, and all the objects stored in penObjects the image drawPen.

An object can add itself to start drawing or remove itself to stop drawing. This is simpler than going via NotificationCenter.

fft buffer sizes > 1024 are not supported

This is because buf.getn can only fetch up to 1024 values (OSC limit?).

removed frombin - tobin as I find little use for zooming in to part of a spectrum and it complicates the code

added toggle tryout.sc + make code palette w. key shortcuts

DocSession:load provides new session if not found in archive

This is important when installing lilt2 to a new computer that does not have any sessions stored.

code parser should ignore lines where //: is followed by spce

PerformanceWindow should re-parse code on changing docs

add ‘doOnce’ message to Function

Function registers itself to notifier and does not reevaluate.

Important for booting servers / scopes only once.

! marked items in DocListWindow type files can use this automatically. Something like:

{ codeString.interpret }.doOnce instead of: { codeString.interpret }.value

code item pane does not refresh properly

At some point the older items remain on the pane together with the newly selecte ones.

Could not remedy that. Suggestion: Try using EZListView instead.

2011-04-21 Thursday

added load, play, loadDefault methods to Buffer class

2011-04-23 Saturday

function hashKey is taken from def.sourceCode, not def.code

This is because, for example:

{ WhiteNoise.ar(0.2) } and { WhiteNoise.ar(0.1) }

have the same code:

Int8Array[ 0, 0, 64, -80, -62, 52, -14 ]

So now, in order for a function to be treated as “unique” by UniqueFunction, it must have exactly the same source code string.

Note: function.hashKey is used by UniquePlay.

add chain, Udef, Ubuf to load synthdefs and buffers before creating a synth

Design of UniqueBuffer

Templates from existing classes to consider

BUFFER: *new { arg server, numFrames, numChannels, bufnum;} *alloc(server, numFrames, numChannels, completionMessage, bufnum) *read { arg server, path, startFrame = 0, numFrames = -1, action, bufnum; } *read(server, path, startFrame, numFrames, action, bufnum)

UNIQUESYNTH: *new { | key, defName, args, target, addAction=\addToHead | ^super.new(key, defName ?? { key.asSymbol }, args, target, addAction);

} init { | what, args, target, addAction … moreArgs | }

Interface for UniqueBuffer: Class methods, synonyms, utilities
Methods modeled after Buffer class methods

MODIFIED, works like Buffer:alloc *new { | key, server, numFrames, numChannels, action | } like Buffer:alloc, with action executed as soon as info is received, no bufnum allocates immediately, boots buffer if needed

*read { | key, server, path, startFrame = 0, numFrames = -1, action | } read from file. Boot buffer if needed. Store in library at [buffers, server:key]

NOT USED: *alloc( | key, server, numFrames, numChannels, completionMessage, bufnum | ) allocate immediately. Boot server if needed.

Methods for convenient use

*play { | func, args | } play last selected buffer or default buffer if none selected

*load { | func, args | } load with file open dialog window, play if func is given

*select { | func, args | } open list of buffers, select one and execute func if provided. selected buffer stays for next calls of “play” or spectrogram.

*spectrogram { | func, args | }

*clear { | server | } clear all UniqueBuffers on server

Synonyms of convenient methods on Buffer class

*play { | func, args | } play last selected buffer or default buffer if none selected

*load { | func, args | } load from file and play if given func

*select { | func, args | }

*spectrogram { | func, args | }

*clear { | server | } clear all UniqueBuffers on server

UniqueBuffer access methods for String and symbol

String:ubuf(func) -> get / load the UniqueBuffer corresponding to this path, on the default server if func is provided, it is used to play the buffer

Symbol:ubuf(func) -> get the UniqueBuffer registered at the default buffer under this string if func is provided, it is used to play the buffer

Designing the code: argument massage

*new { | key, server, numFrames, numChannels, bufnum | ^super.new(key, defName ?? { key.asSymbol }, args, target, addAction); }

*alloc {

}

*/

2011-04-26 Tuesday

add doOnce and forkOnce methods to function

2011-04-29 Friday

add Symbol:playDef

UniqueObject *mainKey now returns [this]

2011-04-30 Saturday

decouple coloring scheme from Panes and add it to non-gittable private startup file

debug Symbol:synth method

2011-05 May

2011-05-01 Sunday

UniqueBuffer:play crashes on multiple starts, using mplay instead

UniqueBuffer:play therefore now uses Function:mplay. This is not a major handicap.

2011-05-02 Monday

UniqueBuffer:load loads also the default buffer if not loaded

A minor glitch, but should be looked into.

PrivateBusSynth, SignalPoller

Extend UniqueSynth class with subclasses:

PrivateBusSynth: adds a private Bus and redirects the output of the synth to it. For analysis synths, effects etc. The bus gets freed as soon as the UniqueSynth stops.

SignalPoller: Adds a synchronized routine (rsynca) that polls the output of the synth to the private bus, or an anasysis buffer, and shares the data via a list of functions with other processes.

2011-05-04 Wednesday

alternative names for UniqueObject?

ObjectService? ObjectRegistry? ObjectServer?

PersistentObject? LibObject?

Many small bugs have been removed. Library is ready for alpha testing

Added WaitForServer.new to String:fork. Snippets don’t need it any more

2011-05-05 Thursday

added toggle server auto boot for code evaluation

If Code class variable autoBoot is set to true, then evaluating a code snippet with Cmd-shift-x will call WaitForServer.new, thereby ensuring that any calls to ‘wait’ will be in sync with the server booted.

2011-05-06 Friday

Spectrograph alpha version complete, added Pen Object Test

Added theme switching with DocThemes class

Added addListener method

Merged lilt2 to master, added tag v1.0alpha

Add doWhen to UniqueObject to do when object is initialized

doWhen { | condition, action | // Some objects created by makeFunc may need time to initialize { while { condition.(this).not } { 0.1.wait }; action.(this); }.fork(AppClock) }

2011-05-07 Saturday

” … and her name was Elemenbí. ”

Elemenbí (L. M.: N. B!)

2011-05-08 Sunday

Completed Spectrograph simplification

2011-05-09 Monday

Fixed ServerPrep, Spectrograph, UniqueBuffer, Function:play, Examples

Added Pattern support: EventStream, UniqueStream, Function:sched. Also SynthPrep uses OSCpathResponder for exact boot timing

2011-05-10 Tuesday

improved help template, added some doc, especially on EventStream and UniqueSynth

Summary of ideas in this lib

ServerPrep
  • Obviate the need to boot the server when starting synths
  • Ensure that Buffers and SynthDefs are allocated / sent to the server before starting synths, efficiently.
  • Provide a safe way for starting synth and routine processes when the server boots or when the tree is inited, ensuring that SynthDefs and Buffers will be loaded first

Classes involved:

  • ServerPrep
  • ServerActionLoader
  • SynthLoader
  • DefLoader
  • BufLoader
  • RoutineLoader
  • UniqueBuffer
  • Udef
UniqueSynth
  • Simplify the creation and control of Synths by storing them in a dictionary for later access, and by providing utility methods for controlling the duration and release time, for synchronizing the execution and life time of routines pertaining to a synth, and for attaching other objects that react to the start and end of a synth.

Example of how UniqueSynth can simplify the code required:

Without Symbol:mplay

(
{
	loop {
		{ 	var synth;
			synth = Synth(\default, [\freq, (25..50).choose.midicps]);
		  	0.1.wait;
		  	synth.release(exprand(0.01, 1.0));
		}.fork;
		[0.1, 0.2].choose.wait;
	};
}.fork;
)

Using Symbol:mplay

(
{
	loop {
		\default.mplay([\freq, (25..50).choose.midicps]).dur(0.1, exprand(0.01, 1.0));
		[0.1, 0.2].choose.wait;
	};
}.fork;
)
EventStream, Function:sched and Function:stream

Simplify the creation and access of Streams from Patterns and their use with Routines and Functions scheduled for repeated execution.

Example: Simplify the above code even further, while enabling control of dtime (and any other parameters) via patterns:

(
{	// Symbol:stream creates and / or accesses the stream as appropriate: 
	\default.mplay([\freq, \freq.prand((25..50), inf).midicps]).dur(0.1, exprand(0.01, 1.0));
	\duration.stream(Prand([0.1, 0.2], 20)); // play 20 events only
}.stream; 	
)

Note: symbol.stream(Prand(…)) is equivalent to \symbol.prand(…)

Object methods for easy messaging via NotificationCenter

Simplify the connection of objects for sending messages to each other via NotificationCenter. Automate the creation of mutual NotificationCenter registrations to messages, and their removal when an object receives the message objectClosed.

One beneficial effect of this is that it is no longer needed to check whether an object stored in a variable is nil in order to decide whether to send it a message. One can create messaging interconnections between objects without storing one in a variable of the other, and one can safely send a message to an object before it is created or after it is no longer a valid receiver of that message.

Code

Enable the selection of parts of a SuperCollider document separated by comments followed by :, the movement between such parts, and the execution of those parts through keyboard shortcuts. Additionally, wrap these code parts in a routine so that number.wait messages can be written straight in the code, without wrapping them in { }.fork or Routine({ }).

Also ensure that the code will run after the default server is booted and the Buffers and SynthDefs defined as Udefs in a Session have been loaded.

Shortcuts provided are:

Command-shift-x: Evaluate the code in an AppClock routine, after booting the default server if needed Command-shift-alt-x: Evaluate the code in a SystemClock routine, after booting the default server if needed Command-shift-v: Evaluate and post the results of the code, without routine or server booting Command-shift-j: Select the next code part Command-shift-k: Select the previous code part

Panes

Arrange Document windows on the screen conveniently for maximum view area on the screen. Provide 2 layouts: single pane and 2 panes side by side, with keyboard shortcuts for switching between them. Provide an auto-updating document list palette for selecting documents by mouse or by string search. Provide a way for switching between a dark colored document theme and the default document theme via keyboard shortcuts, with automatic updating of the coloring of all relevant documents.

Dock

Provide some useful shortcuts for common tasks: browseUserClasses : Open a list of all classes defined in the user’s Application Support directory. Typing return on a selected item opens the code file with the definition of this class.

insertClassHelpTemplate : Insert a template for documenting a class named after the name of the document. Inserts listings of superclasses, class and instance variables and methods.

openCreateHelpFile : Open a help file for a selected user class. Automatic creation of the file is reserved to code residing outside the distribution files of this library.

showDocListWindow : An auto-updating window listing all open Documents, with selection by mouse click or by text search.

closeDocListWindow : Close the document list window

Spectrograph

An example application showing some of the features of this library. Creates a window showing a live running spectrogram of one of the audio channels. The fft polling process for the spectrogram is persistent, that is, it starts as soon as the server boots and re-starts if the server’s processes are killed by Command-. It (optionally) stops when the Spectrograph window is closed.

Devise scheme for chaining scheduled function execution

Orgmode-SC integration via attachments

(With Aris Bezas)

Added ./Extensions/Examples directory to master branch and attached it here to test orgmode link integration.

2011-05-11 Wednesday

Code list ignores comments that have a space after the : (“//: “)

So you can write in a document this: //:Example 1

{ WhiteNoise.ar(0.1) }.play;

//: End of above example

Some text here. The part here will not be listed as a code snippet in the Code list window. (Cmd-})

//:Next example

\window.window;

2011-05-12 Thursday

Chain / EventStream debugged

Debug environment evaluation in Chain, EventStream, remove .next from EventStream new.

2011-05-14 Saturday

Modified Meta_Exception:new to reset ServerPrep, resuming evaluation with Cmd-Shift-X

/*

Reset ServerReady if an Exception occurs, to enable restarting the next time that ServerReady is needed.

*/

  • Exception {

    *new { arg what; var backtrace; // permit to use Cmd-Shift-X for evaluating code again. See classes Code and ServerPrep ServerPrep.initClass; if (debug) { backtrace = this.getBackTrace.caller }; ^super.newCopyArgs(what ? this.name, backtrace) }

}

SynthLink added, timing mechanism + EventStream modified

Tested nested chains, added chain stop, Symbol:chain, chainSeq

Debug stopping in chains: Sometimes synths continue

2011-05-22 Sunday

Rename UniqueObject class to Resource

2011-05-26 Thursday

Keyboard shortcuts for Class, Buffer and SynthDef lists

Cmd-Ctl-C: Class list Cmd-Ctl-S: Synthdef List Cmd-Ctl-B: Buffer list

2011-05-30 Monday

Panes and DocTheme activation should be per kbd command, not per default

sort out symbol buffer and other playing syntax

Should be simplified. Try to follow one principle: the symbol that gets the message is the one that stores the resulting new resource.

simplify synthresource mapping mechanism :busresource:synthresource

\symbol.map(\param, optional: symbol) ->

symbol.synth.map(param, symbol ?? (symbol ++ _ ++ param).control.index )

\symbol.mapDef(\param, defname, args (target???) ) ->

Like above, but start a synth with the defname and args and send its output to the bus.

\symbol.mapFunc(\param, function, args) ->

Like above, but start a synth with the function and args and send its output to the bus.

2011-06 June

2011-06-06 Mobnday

List of machine listening / feature UGens with notes

UGens that output 0-1 changes
Onsets Onset detector (0-1)

Onsets.kr(chain, threshold, odftype)

An onset detector for musical audio signals - detects the beginning of notes/drumbeats/etc. Outputs a control-rate trigger signal which is 1 when an onset is detected, and 0 otherwise.

chain - an FFT chain threshold - the detection threshold, typically between 0 and 1, although in rare cases you may find values outside this range useful odftype - the function used to analyse the signal (options described below; OK to leave this at its default value)

DetectSilence *ar(input, amp, time, doneAction) (0-1)
PV_HainsworthFoote

FFT onset detector based on work described in

Hainsworth, S. (2003) Techniques for the Automated Analysis of Musical Audio. PhD, University of Cambridge engineering dept. See especially p128. The Hainsworth metric is a modification of the Kullback Liebler distance.

The onset detector has general ability to spot spectral change, so may have some ability to track chord changes aside from obvious transient jolts, but there’s no guarantee it won’t be confused by frequency modulation artifacts.

Hainsworth metric on it’s own gives good results but Foote might be useful in some situations: experimental.

*ar(buffer, proph=0.0, propf=0.0, threshold=1.0, waittime=0.04)

PV_JensenAndersen

FFT feature detector for onset detection based on work described in

Jensen,K. & Andersen, T. H. (2003). Real-time Beat Estimation Using Feature Extraction. In Proceedings of the Computer Music Modeling and Retrieval Symposium, Lecture Notes in Computer Science. Springer Verlag.

First order derivatives of the features are taken. Threshold may need to be set low to pick up on changes.

*ar(buffer, propsc=0.25, prophfe=0.25, prophfc=0.25, propsf=0.25, threshold=1.0, waittime=0.04)

buffer- FFT buffer to read from.

propsc- Proportion of spectral centroid feature.

prophfe- Proportion of high frequency energy feature.

prophfc- Proportion of high frequency content feature.

propsf- Proportion of spectral flux feature.

threshold- Threshold level for allowing a detection

waittime- If triggered, minimum wait until a further frame can cause another spot (useful to stop multiple detects on heavy signals)

UGens that output continuous values
Amplitude.kr(in, attackTime, releaseTime, mul, add)
Loudness sones = Loudness.kr(chain, smask=0.25, tmask=6)

chain [fft] - Audio input to track, which has been pre-analysed by the FFT UGen; see examples below for the expected FFT size smask [sk] - Spectral masking param: lower bins mask higher bin power within ERB bands, with a power falloff (leaky integration multiplier) of smask per bin tmask [sk] - Temporal masking param: the phon level let through in an ERB band is the maximum of the new measurement, and the previous minus tmask phons

Peak Peak.ar(in, trig)

Outputs the peak amplitude of the signal received at the input.

PeakFollower.ar(in, decay)

Outputs the peak amplitude of the signal received at the input. if level is below maximum, the level decreases by the factor given in decay.

Pitch autocorrelation pitch follower

#freq, hasFreq = Pitch.kr(in, initFreq, minFreq, maxFreq, execFreq, maxBinsPerOctave, median, ampThreshold, peakThreshold, downSample, clar)

ZeroCrossing zero crossing frequency follower

ZeroCrossing.ar(in)

MFCC mel frequency cepstral coefficients MULTICHANNEL !!!!!

#coeff1, coeff2, … = MFCC.kr(chain, numcoeff=13) // coeffn -> kr signal. (OutputProxy).

Slope slope of signal

Slope.ar(in, mul, add) Slope.kr(in, mul, add)

Measures the rate of change per second of a signal. Formula implemented is:

out[i] = (in[i] - in[i-1]) * sampling_rate

SpecCentroid Spectral centroid

SpecCentroid.kr(chain)

Given an FFT chain, this measures the spectral centroid, which is the weighted mean frequency, or the “centre of mass” of the spectrum. (DC is ignored.)

This can be a useful indicator of the perceptual brightness of a signal.

SpecFlatness Spectral Flatness measure

SpecFlatness.kr(chain)

Given an FFT chain this calculates the Spectral Flatness measure, defined as a power spectrum’s geometric mean divided by its arithmetic mean. This gives a measure which ranges from approx 0 for a pure sinusoid, to approx 1 for white noise.

SpecPcile Find a percentile of FFT magnitude spectrum

SpecPcile.kr(chain, fraction)

Given an FFT chain this calculates the cumulative distribution of the frequency spectrum, and outputs the frequency value which corresponds to the desired percentile.

2011-06-08 Wednesday

Debug Chain help parallel examples crash when triggered from button window

Started reorganizing code in quarks, following mc method

Local Quark folders to use:

quarks.local.core : Core library parts quarks.local.projects : Project code

2011-07 July

2011-07-17 Sunday

GitQuarks should copy installed version back to uninstalled and restore timestamps for git transparency

2011-10 October

2011-10-15 Saturday

reorganized library into quarks

Added + tweaked local Quark mechanism by Martin Carle. Documented Quark installation procedure and added instructions in README files. Quarks are installed as symlinks in the Extension library (not as copies).

Possible scheme for restoring quark configurations from Git branches

Problem:

When switching from one Git branch to another, links to some quark folders which were installed may be missing. How to restore the quark configuration that belongs to a particular branch of a Git repository?

Note: What happens when the folder of an installed quark is missing because the branch does not contain it? Testing this with SC 3.4.4 on MacOS X 10.7.2: The missing quark is simply not included in the library, but SC compiles OK. When the folder is recreated by switching to another branch, then the link to that folder works again and the quark is included in the current SC compile configuration.

Suggested solution

Each branch should remember the quark configuration that was last installed by the user. This configuration should be installed when the user re-compiles.

Implementation method

SC should be able to recognize what git branch is currently checked out. Solution: Write the name of the branch in a file that is saved in the repository.

The user should recall which configuration of quarks was last installed for each branch. This configuration can be different for each user. Therefore, the configuration is saved in the user application support folder, not in the git repository.

The configurations are therefore saved as a multi-level dictionary in an archive in the user application support folder. The structure of the dictionary is:

  • level 1: name of repository
    • level 2: name of branch For each branch in each repository: List of names of quarks installed.

This configuration should be saved at each time that any quark is installed or deinstalled using the quarks GUI.

Additionally, it is proposed to save a default quark configuration for each branch, inside the branch, possibly in the same file that saves the name of the branch. If a user-specific configuration for this branch is not found, then a dialog pops up and prompts the user to install the default configuration.

2011-10-26 Wednesday

merging mc work from assembla

Merge procedure and setup to include two remotes in one local repository:

The assembla remote repository is protected and is used by mc and iz for pushing code collaboratively.

The github repository is public and is used for sharing code with everyone.

The assembla repository is linked to the master branch. The github respository is linked to the LogIn branch.

checked out all mc mods to Panes, Dock from assembla/master to github/LogIn

2011-10-28 Friday

quarks install in quark group directory

2012

2012-04 April

2012-04-17 Tuesday

TODO: Simplify Panes + UserPrefs

UserPrefs may use the global Archive, which is the standard method for saving objects to disc for the user.

Simplify Panes:

  • Where should menu items such as Boot/Quit default server go? New class …
  • Review and simplify pane placement scheme, especially:
    • *defaults
    • protoPanePos
    • *arrange1Pane, *arrangeMultiPanes
    • review role of *multiPaneWidth
    • *nextPane