/* CMP_avalanche.h version 1.35 by Pieter Suurmond, june 17, 2004. Defines memory structure of AVALANCHE objects and their textfile format. Latest version available at: http://kmt.hku.nl/~pieter/SOFT/ Copyright (c) 2001-2004 Schreck Ensemble - Pieter Suurmond Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. Any person wishing to distribute modifications to the Software is requested to send the modifications to the original developer so that they can be incorporated into the canonical version. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. (* SYNTAX OF COMPARSER AVALANCHE FILES =================================== Using Extended Backus Naur Form (EBNF) according to ISO/IEC 14977 : 1996(E) (see http://www.cl.cam.ac.uk/~mgk25/iso-ebnf.html or the official document) where square brackets [] denote zero or one time; curly brackets {} denote zero or more times; commas denote concatenation; and vertical bars denote options. Additional restrictions that cannot be expressed in EBNF (and some semantics) are mentioned in the form of comments. When an avalanche file is created automatically (possibly overwriting another file), its' filename is derived from the originating audio file. Optional starttime and endtime are included in the name. The name is concluded by the suffix '.avl'. *) audio filename = name, ['.',('A'|'a'),('I'|'i'),('F'|'f'),['F'|'f']]; avalanche filename = name, [starttime, endtime], '.avl'; starttime = time; endtime = time; time = '-', minutes, 'm', seconds, 's', milliseconds; minutes = 2 * decimal digit (* And also < 60. *); seconds = 2 * decimal digit (* And also < 60. *); milliseconds = 3 * decimal digit (* Implies < 1000. *); (* An avalanche file consists of lines, it should contain 2 headerlines and at least one neuron line. *) avalanche file = { cmp comment }, (fps line, bfq line) | (bfq line, fps line), neuron line, { neuron line }; (* All lines beginning with a '#' chararcter are ignored. The fps line and bfq line are mandatory, specifying the number of feature vectors per second and the spectral base frequency used during analysis. Both lines may appear in any order but they must preceed the neuron lines. *) fps line = ('F'|'f'), ('P'|'p'), ('S'|'s'), '=', fps, new line, { new line | cmp comment }; fps = decimal digit, 2 * [decimal digit], (* 5 =< fps =< 200. *) ['.', [7 * decimal digit]]; bfq line = ('B'|'b'), ('F'|'f'), ('Q'|'q'), '=', bfq, new line, { new line | cmp comment }; bfq = decimal digit, 2 * [decimal digit], ['.', [7 * decimal digit]]; (* A neuron line starts with the number of feature vectors clustered followed by a colon. Then a number of scalars follow, separated by spaces. All neuron lines should contain the same number of scalars. *) neuron line = duration, ':', scalar, { scalar }, new line, { new line | cmp comment }; duration = decimal digit, [decimal digit]; (* cluster time. *) scalar = hspace, ['-'], decimal digit, 3 * [decimal digit]; (* Global definitions. *) hspace = (' ' | ?ISO 6429 character Horizontal Tabulation?), {' ' | ?ISO 6429 character Horizontal Tabulation?}; cmp comment = '#', { character }, new line; (* As in ISO/IEC 14977 EBNF. *) decimal digit = '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9'; new line = { ? ISO 6429 character Carriage Return ? }, ? ISO 6429 character Line Feed ?, { ? ISO 6429 character Carriage Return ? }; */ /*----------------------------------------------------------------------------*/ #define kCMP_avalanche_file_suffix (".avl") /* Filename extension of avalan- */ /* che files, including the dot. */ /*----------------------------------------------------------------------------*/ typedef struct AVALANCHE_STRUCT* AVALANCHE; /* No separate datastructure for */ struct AVALANCHE_STRUCT /* single processing element. */ { /* Read-only members written just once by function read_AVALANCHE(): */ AVALANCHE next; /* Avalanche(s) in parallel or NULL. */ char* filename; /* Name of originating audio file. */ long ms_start, /* Start and end in milliseconds. When */ ms_end; /* both zero, the complete audiofile. */ /* FPS is not here but in parent struct. */ double baseFrequency; /* Frequency [Hz] lowest varidist band. */ short vectorSize; /* Number of scalars per feature vector. */ long numPE; /* Number of processing elements. */ short* weights; /* Array of numPE weight vectors. */ short* durations; /* Array of numPE durations (>=1). */ /* Runtime members set by reset_runtime_NETWORK() and follow_AVALANCHES():*/ long rt_startPE, /* For runtime optimisation. */ rt_stopPE; short* rt_outputs; /* Array of numPE output activities. */ }; /*----------------------------------------------------------------------------*/ /* Adds a single avalanche to the linked list of avalanches (avalanches are run in parallel and lead to the next node in the network during following). Returns zero on success, then the new object's address is written into *handle. Returns nonzero on failures, then, if necessary the object is destroyed and NULL is written into *handle. First looks for a textfile with clustered feature vectors. If that file is not present yet, an aiff file will be analysed and such a textfile will be generated from the audiofile. So argument filename may be the name of a avalanche file or the name of an audiofile. The length of filename is checked and may not exceed 63 chars. The number of feature vectors per second specified by argument fps is checked against the number specified in the textfile. If the textfile is not available, during analysis of the audiofile (which generates that textfile) the correct FFT size is choosen. Also allocates runtime memory structures to run the avalanche, but it does not reset runtime structures (reset_runtime_NETWORK() is ex- pected to do that!). The last argument may be NULL, but if it is not, diagnostic messages may be wriiten to it. (Since 1.31, it doesn't printf to stdout implicitly any longer.) */ int AVALANCHE_read(const char* name_version, AVALANCHE* handle, const char* filename, long start, long end, double fps, FILE* msg); /*----------------------------------------------------------------------------*/ /* Releases all avalanches after *handle. When *handle points to the root of the linked list, the complete list deleted. When *handle points to the last item in the linked list, only the last item is removed. */ int AVALANCHES_destruct(AVALANCHE *handle); /*----------------------------------------------------------------------------*/ /* Reads 'numFrames' feature vectors from 'vectors' (which is a non-circular buffer), clusters them and writes them to textfile with name 'filename'. Performs on-the-fly VECTOR CLUSTERING. Assumes incoming vectors are already normalized. Calculates successive vector dot products, which is faster than calculating successive Euclidian distances. To inhibit vector clustering, call with argument maxCluster=0 which forces another scheme, in principal, calling with maxCluster=1 should result exactly the same but is less CPU-efficient. To inhibit silence cropping, make argument silenceCropping high enough. Returns 0 when everything went ok. Negative errors are more serious than positive errors and are supposed to quit ComParser after returning. It may seem weird, but this function is called by read_AVALANCHE(). */ int AVALANCHE_write(const char* name_version, const char* filename, /* File to be created/overwrt. */ double fps, /* Feature vectors per second. */ double bfq, /* Base frequency of FFT. */ short numScalars, /* Need to know size of vector. */ long numVectors, short* vectors, long clusterTreshold, /* V dot product. */ short maxCluster, /* To repeat. */ short silenceCropping); /*----------------------------------------------------------------------------*/ /* None of the arguments may be NULL. Call reset_runtime_NETWORK() before you call this function (or function follow_NETWORK() which calls this function). When argument debugAvalanche is nonzero, progress in the avalanche structure is diplayed on the console. The avalanche object knows how many scalars are contained by the vector! */ int AVALANCHES_follow(const short* input_vector, /* AVALANCHE object knows size! */ AVALANCHE avalanches, /* Linked list of (parallel) avls. */ FILE* msg, /* May be NULL. */ int debugAvalanche); /* 0 for no printfs() to console. */ /*----------------------------------------------------------------------------*/ /* Saves a graphic image of the avalanche layer to disk. */ int AVALANCHE_jpg(AVALANCHE avalanche, /* Avalanche object. */ const char* name_version, /* Software revision. */ FILE* msg); /* May be NULL, stdout, etc. */ /*----------------------------------------------------------------------------*/ /* Returns the number of characters written to character array dst. Should always return 10. Caller should guarentee, there is enough room to print 10 chars in dst. */ int AVALANCHE_write_milliseconds(long ms, char* dst);