./../../src/spectra.lsp

## sc/spectra [ Modules ]

[ Top ] [ Modules ]

NAME

     spectra

     File:             spectra.lsp

     Class Hierarchy:  none (no classes defined)

     Version:          1.0.10

     Project:          slippery chicken (algorithmic composition)

     Purpose:          Definition of the spectral data for piano and other
                       instruments' notes. We'll use this data for
                       the calculation of chord dissonance values in the chord
                       class's calculate-dissonance method.

     Author:           Michael Edwards: m@michael-edwards.org

     Creation date:    July 27th 2015

     $$ Last modified: 12:27:57 Tue Feb  2 2016 GMT

     SVN ID: $Id: spectra.lsp 5359 2015-07-24 20:53:22Z medward2 $

## spectra/get-spectra-al [ Functions ]

[ Top ] [ spectra ] [ Functions ]

DATE

     August 6th 2015, Edinburgh

DESCRIPTION

     Create an assoc-list of spectral data by doing spectral analysis of all the
     sound files contained in a given directory. The aim is to extract the
     spectral data for harmonic partials, so we specifically look for ascending
     partials as close as possible to integer multiples of the sample sound
     file's fundamental frequency, as detected from the file name (see below).

     By default we average spectra over three separate readings at 300, 400, and
     500 milliseconds. We do this in order to avoid spectral anomalies at any
     fixed point in any of the sound files, and of course to skip the onset
     transient and any inharmonicities therein.

     As the extensive analysis and processing here will take some computation
     time, in order to create our default spectral data for calculating a
     chord's dissonance or spectral centroid, I've performed the analysis on
     some of my local sample libraries. By then using the assoc-list method
     print-for-init I've copied the data into separate text files for reading
     into the +slippery-chicken-spectra+ global assoc-list and thus making these
     available to all slippery-chicken users. By modifying the examples at the
     bottom of this file, similar sample directories' spectral data could be
     added to this global.

ARGUMENTS

     - the path to the samples directory. This should be something suitable for
     passing to the (directory) function so we'll need the extension of the sound
     files (see "*.wav" in the example below).
     - a function for processing the filenames (as a string, with no directory
     or extension e.g. "Stein-R(A0)-V(085)-dB(3478)-T(ML)-M(28)-P(2126-03-01)")
     in order to return the MIDI note number of the sample in that file. This
     whole approach is predicated on the assumption that sample file names will
     contain such pitch data. If that is not the case then get-spectra-al will
     be of no use. See the akoustik-piano-name and violin-ensemble-name
     functions below for examples.

OPTIONAL ARGUMENTS

      Keyword arguments:
     - :force-harmonics: whether to look for harmonic partials or not. If this
        is nil then the returned spectra will be the strongest by amplitude
        irrespective of their harmonicity. Default = t
     - :harmonic-tolerance: the maximum deviation from the exact integer
        partial. Default = 0.15
     - :fftsize: The FFT window size for spectral analysis. Default = 4096
     - :num-partials: the number of partials to identify and return.
        Default = 12
     - :id: The default ID for the resultant assoc-list. Default = 'spectra
     - :analysis-points: The times in milliseconds at which to do the spectral
        analysis and extract averages. If no averaging is necessary simply pass
        one starting value as a list. Default = '(300 400 500)

RETURN VALUE

     An assoc-list object whose keys are the MIDI note numbers associated with
     the spectral information of sample sound files. Each of these is in the
     form of a two element list: a list of fundamental scalers and a list of
     their amplitudes (normalised to 1.0).

EXAMPLE

    (get-spectra-al "/path/to/samples/*.wav"
                    #'violin-ensemble-name :id 'violin-ensemble)
    -->
    ASSOC-LIST: warn-not-found T
    CIRCULAR-SCLIST: current 0
    SCLIST: sclist-length: 21, bounds-alert: T, copy: T
    LINKED-NAMED-OBJECT: previous: NIL, this: NIL, next: NIL
    NAMED-OBJECT: id: VIOLIN-ENSEMBLE, tag: NIL,
    data: (
    NAMED-OBJECT: id: 56, tag: NIL,
    data: ((0.9889743194880222d0 2.0263850081954717d0 2.9990610385449314d0
            4.024036707283989d0 5.032546599880615d0 6.013292183763263d0
            7.0551329128964655d0 8.049590274637817d0 9.032029362954297d0
            10.017427921485291d0 11.0461040956976d0 12.028523416637086d0)
           (0.1748299156810844d0 0.6666103041159978d0 0.740572572283973d0
            0.37090168062541756d0 0.2529382535743205d0 0.19313279338531672d0
            0.290088638695093d0 0.20008736984066355d0 0.12280861470679348d0
            0.15534581915388804d0 0.11772253740784348d0 0.11703054477270619d0))
    ...

SYNOPSIS

    #+clm
    (defun get-spectra-al (sample-dir name-fun
                           &key (force-harmonics t) (harmonic-tolerance 0.15)
                             (fftsize 4096) (num-partials 12) (id 'spectra)
                             ;; millisec times of fft analysis
                             (analysis-points '(300 400 500)))