PageRenderTime 54ms CodeModel.GetById 22ms app.highlight 11ms RepoModel.GetById 10ms app.codeStats 0ms

/flash/src/js/audio.js

http://echo-nest-remix.googlecode.com/
JavaScript | 184 lines | 157 code | 23 blank | 4 comment | 15 complexity | 25839d3a494d82e25ac126db23b0526d MD5 | raw file
  1function AudioAnalysis(analysis) {
  2    extend(this, analysis);
  3
  4    var duration = this.metadata.duration;
  5
  6    if (this.sections) {
  7        this.sections = AudioQuantumList.fromSections(this.sections);
  8        this.sections.analysis = this;
  9    }
 10    if (this.bars) {
 11        this.bars = AudioQuantumList.fromEvents('bar', this.bars, duration);
 12        this.bars.analysis = this;
 13    }
 14    if (this.beats) {
 15        this.beats = AudioQuantumList.fromEvents('beat', this.beats, duration);
 16        this.beats.analysis = this;
 17    }
 18    if (this.tatums) {
 19        this.tatums = AudioQuantumList.fromEvents('tatum', this.tatums, duration);
 20        this.tatums.analysis = this;
 21    }
 22    if (this.segments) {
 23        this.segments = AudioQuantumList.fromSegments(this.segments);
 24        this.segments.analysis = this;
 25    }
 26}
 27
 28function AudioQuantum() {
 29    this.start = 0;
 30    this.end = 0;
 31    this.duration = 0;
 32}
 33
 34extend(AudioQuantum.prototype, {
 35    setDuration: function(duration) {
 36        this.duration = duration;
 37        this.end = this.start + duration;
 38    },
 39
 40    setEnd: function(end) {
 41        this.end = end;
 42        this.duration = this.end - this.start;
 43    },
 44
 45    parent: function() {
 46        // TODO handle error
 47        var uppers = this.container.analysis[AudioQuantum.parentAttributes[this.container.kind]];
 48        return uppers.that(selection.overlap(this))[0];
 49    },
 50
 51    children: function() {
 52        // TODO handle error
 53        var downers = this.container.analysis[AudioQuantum.childrenAttributes[this.container.kind]];
 54        return downers.that(selection.areContainedBy(this));
 55    },
 56
 57    group: function() {
 58        var parent = this.parent();
 59        if (parent) {
 60            return parent.children();
 61        }
 62        else {
 63            return this.container;
 64        }
 65    },
 66
 67    localContext: function() {
 68        var group = this.group();
 69        return [group.indexOf(this), group.length];
 70    }
 71});
 72
 73extend(AudioQuantum, {
 74    parentAttributes: {
 75        bar: 'sections',
 76        beat: 'bars',
 77        tatum: 'beats'
 78    },
 79
 80    childrenAttributes: {
 81        section: 'bars',
 82        bar: 'beats',
 83        beat: 'tatums'
 84    }
 85});
 86
 87function AudioQuantumList(kind) {
 88    var array = extend([], AudioQuantumList.Methods);
 89    array.kind = kind;
 90    return array;
 91}
 92
 93AudioQuantumList.Methods = {
 94    that: function(filter) {
 95        var result = new AudioQuantumList(this.kind);
 96
 97        for (var i = 0; i < this.length; i++) {
 98            var aq = this[i];
 99            if (filter(aq)) {
100                result.push(aq);
101            }
102        }
103        return result;
104    },
105
106    orderedBy: function(fn, descending) {
107        var result = new AudioQuantumList(this.kind);
108        result.push.apply(result, this);
109        result.sort(function(a, b) {
110            var aa = fn(a);
111            var bb = fn(b);
112            if (aa > bb) {
113                return 1;
114            }
115            if (aa < bb) {
116                return -1;
117            }
118            return 0;
119        });
120        // TODO
121        if (descending) {
122            result.reverse();
123        }
124        return result;
125    }
126};
127
128extend(AudioQuantumList, {
129    fromEvents: function(kind, events, duration) {
130        var aqs = new AudioQuantumList(kind);
131
132        var previousAq = new AudioQuantum();
133        previousAq.start = 0;
134        for (var i = 0; i < events.length; i++) {
135            var event = events[i];
136            var aq = new AudioQuantum();
137
138            aq.start = aq.value = event.value;
139            aq.confidence = event.confidence;
140            aq.container = aqs;
141            aqs.push(aq);
142
143            previousAq.setEnd(aq.start);
144            previousAq = aq;
145        }
146        // TODO audio.py duplicates the duration of the second-to-last event
147        previousAq.setEnd(duration);
148        return aqs;
149    },
150
151    fromSections: function(sections) {
152        var aqs = new AudioQuantumList('section');
153        for (var i = 0; i < sections.length; i++) {
154            var section = sections[i];
155            var aq = new AudioQuantum();
156
157            aq.start = section.start;
158            aq.setDuration(section.duration);
159            aq.container = aqs;
160            aqs.push(aq);
161        }
162        return aqs;
163    },
164
165    fromSegments: function(segments) {
166        var aqs = new AudioQuantumList('segment');
167        for (var i = 0; i < segments.length; i++) {
168            var segment = segments[i];
169            var aq = new AudioQuantum();
170
171            aq.start = aq.value = segment.start;
172            aq.setDuration(segment.duration);
173            aq.pitches = segment.pitches;
174            aq.timbre = segment.timbre;
175            aq.loudnessBegin = segment.startLoudness;
176            aq.loudnessMax = segment.maxLoudness;
177            aq.timeLoudnessMax = segment.maxLoudnessTimeOffset;
178            aq.loudnessEnd = segment.endLoudness;
179            aq.container = aqs;
180            aqs.push(aq);
181        }
182        return aqs;
183    }
184});