Changeset 29893
- Timestamp:
- 2015-05-18T16:42:17+12:00 (9 years ago)
- Location:
- main/trunk/model-sites-dev/respooled/collect/popup-video-respooled
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
main/trunk/model-sites-dev/respooled/collect/popup-video-respooled/etc/collectionConfig.xml
r29890 r29893 17 17 <displayItem assigned="true" lang="en" name="section">section</displayItem> 18 18 </displayItemList> 19 <format> <gsf:template name="choose-title"> 19 <format> 20 <gsf:template name="choose-title"> 20 21 <gsf:choose-metadata> 21 22 <gsf:metadata name="dc.Title"/> … … 27 28 <gsf:default>Untitled</gsf:default> 28 29 </gsf:choose-metadata> 30 31 <xsl:text> </xsl:text> 32 29 33 <gsf:switch> 30 <gsf:metadata name="dc. Creator"/>34 <gsf:metadata name="dc.Description"/> 31 35 <gsf:when test="exists"> 32 <gsf:switch> 33 <gsf:metadata name="dc.Description"/> 34 <gsf:when test="notEquals" test-value="Unknown"> 35 36 <gsf:metadata name="dc.Description"/> 37 38 </gsf:when> 39 </gsf:switch> 36 <gsf:metadata name="dc.Description"/> 40 37 </gsf:when> 41 38 </gsf:switch> … … 249 246 </xsl:call-template> 250 247 --> 248 <!-- 251 249 <h3> 252 250 <xsl:call-template name="choose-title"/> 253 251 </h3> 252 --> 253 254 254 </gsf:template> 255 255 <!-- … … 336 336 <gsf:script src="{$httpCollection}/js/jquery.qtip.min.js"/> 337 337 <gsf:script src="{$httpCollection}/js/qtip-popups.js"/> 338 339 <gsf:script src="{$httpCollection}/js/key-detection.js"/> 340 338 341 <!-- 339 342 MIDI.js library -
main/trunk/model-sites-dev/respooled/collect/popup-video-respooled/js/game-on.js
r29888 r29893 88 88 } 89 89 90 91 function computeMidiStats(track) 92 { 93 var min_midi_pitch = num_midi_pitches-1; 94 var max_midi_pitch = 0; 95 96 var track_chromatic_durations = []; 97 for (var i=0; i<12; i++) { 98 track_chromatic_durations[i] = 0; 99 } 100 101 // Process each block within the track 102 for (var b=0; b<track.length; b++) { 103 var track_block = track[b]; 104 //var base_ctime = track_block.baseCTime; 105 var block_events = track_block.events; 106 107 var block_chromatic_durations = []; 108 for (var i=0; i<12; i++) { 109 block_chromatic_durations[i] = 0; 110 } 111 112 for (var ne=0; ne<block_events.length; ne++) { 113 var midi_pitch = block_events[ne].midiPitch; 114 115 if (midi_pitch < min_midi_pitch) { 116 min_midi_pitch = midi_pitch; 117 } 118 if (midi_pitch > max_midi_pitch) { 119 max_midi_pitch = midi_pitch; 120 } 121 122 var chromatic_pitch = midi_pitch % 12; 123 var chromatic_duration = block_events[ne].duration; 124 block_chromatic_durations[chromatic_pitch] += chromatic_duration; 125 126 track_chromatic_durations[chromatic_pitch] += chromatic_duration; 127 } 128 129 if (!("_computedKey" in track_block)) { 130 var strongest_profile = khKeyDetection(block_chromatic_durations); 131 track_block._computedKey = strongest_profile; 132 console.log("***### key prediction: " + strongest_profile); 133 } 134 135 } 136 137 if (!("_computedKey" in track)) { 138 var strongest_profile = khKeyDetection(track_chromatic_durations); 139 track._computedKey = strongest_profile; 140 } 141 142 return { "max_midi_pitch": max_midi_pitch, "min_midi_pitch": min_midi_pitch}; 143 } 144 145 90 146 function displayActiveTrackLayers(docStorage) 91 147 { … … 116 172 if (track != null) { 117 173 174 175 var midi_stats = computeMidiStats(track); 176 177 if (midi_stats.min_midi_pitch < min_midi_pitch) { 178 min_midi_pitch = midi_stats.min_midi_pitch; 179 } 180 if (midi_stats.max_midi_pitch > max_midi_pitch) { 181 max_midi_pitch = midi_stats.max_midi_pitch; 182 } 183 184 118 185 // calculate range of midi pitches present 186 /* 119 187 for (var b=0; b<track.length; b++) { 120 188 var track_block = track[b]; … … 132 200 } 133 201 } 202 */ 203 134 204 } 135 205 } -
main/trunk/model-sites-dev/respooled/collect/popup-video-respooled/js/key-detection.js
r29892 r29893 1 1 "use strict"; 2 2 3 // From:3 // Key detection algorithm, as described at: 4 4 // http://rnhart.net/articles/key-finding/ 5 6 // (from this web site) .... 7 // Krumhansl-Schmuckler key-finding algorithm (by Carol L. Krumhansl 8 // and Mark A. Schmuckler). The profile numbers came from experiments 9 // done by Krumhansl and Edward J. Kessler. The experiments consisted 10 // of playing a set of context tones or chords, playing a probe tone, 11 // and asking a listener to rate how well the probe tone fit with the 12 // context. You can read about the experiments and the algorithm in 13 // Krumhansl's book Cognitive Foundations of Musical Pitch. (The 14 // experiments are described in Chapter 2. The key-finding algorithm 15 // is described in Chapter 4.) You may be able to read portions of 16 // the book on Google Books. 17 18 19 function khMean(vals) 20 { 21 var len = vals.length; 22 if (len==0) { 23 return 0; 24 } 25 26 var total = 0; 27 28 for (var i=0; i<len; i++) { 29 total += vals[i]; 30 } 31 32 return total/len; 33 } 34 35 function khUnbiased(vals) 36 { 37 var unbiased_vals = []; 38 39 var len = vals.length; 40 if (len==0) { 41 return unbiased_vals; 42 } 43 44 var avg = khMean(vals); 45 46 for (var i=0; i<len; i++) { 47 unbiased_vals.push(vals[i] - avg) 48 } 49 50 return unbiased_vals; 51 } 52 53 54 function khCorrelationCoefficientUnbiased(a1,a2) 55 { 56 var a1_len = a1.length; 57 var a2_len = a2.length; 58 59 if (a1_len != a2_len) { 60 throw "khCorrelationCoefficientUnbiased(): arrays should be of the same length (" + a1_len + " vs " + a2_len + ")"; 61 } 62 var len = a1_len; 63 64 var a1_a2_pair_prod = 0; 65 var a1_square = 0; 66 var a2_square = 0; 67 68 for (var i=0; i<len; i++) { 69 a1_a2_pair_prod += (a1[i]*a2[i]); 70 a1_square += (a1[i]*a1[i]); 71 a2_square += (a2[i]*a2[i]); 72 } 73 74 return a1_a2_pair_prod / Math.sqrt(a1_square * a2_square); 75 } 76 5 77 6 78 //major profile … … 19 91 var kh_minor_profile = [6.33, 2.68, 3.52, 5.38, 2.60, 3.53, 2.54, 4.75, 3.98, 2.69, 3.34, 3.17 ]; 20 92 93 var kh_major_profile_unbiased = khUnbiased(kh_major_profile); 94 95 var kh_minor_profile_unbiased = khUnbiased(kh_minor_profile); 96 21 97 22 98 function khCreatePairing(profile,chromatic_scale_durations,offset) 23 99 { 24 var pairing = []; 25 for (var p=0; p<12; p++) { 26 pairing.push({"p":profile[p],"c":chromatic_scale_durations[(p+s)%12]}); 100 var p = []; 101 var c = []; 102 for (var i=0; i<12; i++) { 103 p.push(profile[i]) 104 c.push(chromatic_scale_durations[(i+offset)%12]); 27 105 } 28 106 29 107 30 return pairing;31 } 32 33 34 function khCreateAllPairings(chromatic_scale_durations ,major_profile,minor_profile)108 return {"p":p, "c":c}; 109 } 110 111 112 function khCreateAllPairings(chromatic_scale_durations_unbiased,major_profile_unbiased,minor_profile_unbiased) 35 113 { 36 114 // chromatic_scale_durations.length = 12 … … 45 123 var scale = chromatic_keys[s]; 46 124 47 major_pairings[scale] = khCreatePairing(major_profile ,chromatic_scale_durations,s);48 minor_pairings[scale] = khCreatePairing(minor_profile ,chromatic_scale_durations,s);125 major_pairings[scale] = khCreatePairing(major_profile_unbiased,chromatic_scale_durations_unbiased,s); 126 minor_pairings[scale] = khCreatePairing(minor_profile_unbiased,chromatic_scale_durations_unbiased,s); 49 127 } 50 128 51 129 return {"major" : major_pairings, "minor" : minor_pairings}; 52 53 } 54 55 130 } 131 132 function khComputeKeyCorrelationCoefficients(key_pairings_unbiased) 133 { 134 var correlations = {}; 135 136 var keys = Object.keys(key_pairings_unbiased); 137 var keys_len = keys.length; 138 139 for (var k=0; k<keys_len; k++) { 140 141 var key = keys[k]; 142 var key_pairing_unbiased = key_pairings_unbiased[key]; 143 144 var correlation_coeff = khCorrelationCoefficientUnbiased(key_pairing_unbiased.p,key_pairing_unbiased.c); 145 correlations[key] = correlation_coeff; 146 } 147 148 return correlations; 149 } 150 151 152 function khComputeAllCorrelationCoefficients(pairings_unbiased) 153 { 154 var major_correlation = khComputeKeyCorrelationCoefficients(pairings_unbiased.major); 155 var minor_correlation = khComputeKeyCorrelationCoefficients(pairings_unbiased.minor); 156 157 return {"major" : major_correlation, "minor" : minor_correlation}; 158 } 159 160 function khFindMaxCorrelation(alignments) 161 { 162 var max_val = 0; 163 var max_key = null; 164 165 var major_minor = [ "major", "minor" ]; 166 167 for (var m=0; m<major_minor.length; m++) { 168 var mm = major_minor[m]; 169 var mm_alignment = alignments[mm]; 170 171 var mm_keys = Object.keys(mm_alignment); 172 173 for (var k=0; k<mm_keys.length; k++) { 174 var key = mm_keys[k]; 175 var correlation_coeff = mm_alignment[key]; 176 if (correlation_coeff>max_val) { 177 max_val = correlation_coeff; 178 max_key = key + " (" + mm + ")"; 179 } 180 } 181 } 182 183 return { "key": max_key, "score": max_val }; 184 } 185 186 function khKeyDetection(chromatic_scale_durations) 187 { 188 // Work out durations of MIDI events folded into octave (60=Middle-C) 189 // (unbiased data) 190 191 //var chromatic_scale_durations = [ 432, 231, 0, 405, 12, 316, 4, 126, 612, 0, 191, 1]; 192 var chromatic_scale_durations_unbiased = khUnbiased(chromatic_scale_durations); 193 194 // Generate all (unbiased) pairings 195 var kh_pairings_unbiased = khCreateAllPairings(chromatic_scale_durations_unbiased,kh_major_profile_unbiased,kh_minor_profile_unbiased) 196 197 // Compute Correlation Coefficients 198 var kh_alignments = khComputeAllCorrelationCoefficients(kh_pairings_unbiased); 199 200 // Pick highest values 201 202 var strongest_profile = khFindMaxCorrelation(kh_alignments); 203 204 console.log("Predicted Key: " + JSON.stringify(strongest_profile)); 205 206 return strongest_profile; 207 208 } 209 210 -
main/trunk/model-sites-dev/respooled/collect/popup-video-respooled/transform/pages/document.xsl
r29890 r29893 1315 1315 1316 1316 <div> 1317 1317 1318 <div id='media-player' style="width: 96%"> 1318 1319 1320 <div class="about-bar"> 1321 <div id="about-titlebar" style="background-image: none; background-color: #2E52A4; width: 97%; float: left; margin-bottom: 10px; z-index: 4; position: relative;"> 1322 About: <xsl:call-template name="choose-title"/> 1323 </div> 1324 1325 <div style="clear: both;"><xsl:comment>clear floats</xsl:comment></div> 1326 1327 <div id="about-area" class="documenttext" 1328 style="display: none; position: absolute: left: 0px; top: 0px; z-index: 1;"> 1329 <xsl:call-template name="fingerprintMetadataBlock" /> 1330 </div> 1331 </div> 1319 1332 1320 1333 <div class="video-player-bar"> … … 1917 1930 <xsl:text disable-output-escaping="yes"> 1918 1931 $(function(){ 1932 transformToTurnstyleBlock("about"); 1933 1919 1934 transformToTurnstyleBlock("video"); 1920 1935 transformToTurnstyleBlock("playlist");
Note:
See TracChangeset
for help on using the changeset viewer.