@ -1,92 +0,0 @@ |
|||||||
import React, { Component } from 'react'; |
|
||||||
import load from 'load-script'; |
|
||||||
|
|
||||||
window.audio_cache = {}; |
|
||||||
|
|
||||||
function load_amrnb() { |
|
||||||
return new Promise((resolve, reject) => { |
|
||||||
if (window.AMR) resolve(); |
|
||||||
else |
|
||||||
load('static/amr_all.min.js', (err) => { |
|
||||||
if (err) reject(err); |
|
||||||
else resolve(); |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
export class AudioWidget extends Component { |
|
||||||
constructor(props) { |
|
||||||
super(props); |
|
||||||
this.state = { |
|
||||||
url: this.props.src, |
|
||||||
state: 'waiting', |
|
||||||
data: null, |
|
||||||
}; |
|
||||||
} |
|
||||||
|
|
||||||
load() { |
|
||||||
if (window.audio_cache[this.state.url]) { |
|
||||||
this.setState({ |
|
||||||
state: 'loaded', |
|
||||||
data: window.audio_cache[this.state.url], |
|
||||||
}); |
|
||||||
return; |
|
||||||
} |
|
||||||
|
|
||||||
console.log('fetching audio', this.state.url); |
|
||||||
this.setState({ |
|
||||||
state: 'loading', |
|
||||||
}); |
|
||||||
Promise.all([fetch(this.state.url), load_amrnb()]).then((res) => { |
|
||||||
res[0].blob().then((blob) => { |
|
||||||
const reader = new FileReader(); |
|
||||||
reader.onload = (event) => { |
|
||||||
const raw = new window.AMR().decode(event.target.result); |
|
||||||
if (!raw) { |
|
||||||
alert('audio decoding failed'); |
|
||||||
return; |
|
||||||
} |
|
||||||
const wave = window.PCMData.encode({ |
|
||||||
sampleRate: 8000, |
|
||||||
channelCount: 1, |
|
||||||
bytesPerSample: 2, |
|
||||||
data: raw, |
|
||||||
}); |
|
||||||
const binary_wave = new Uint8Array(wave.length); |
|
||||||
for (let i = 0; i < wave.length; i++) |
|
||||||
binary_wave[i] = wave.charCodeAt(i); |
|
||||||
|
|
||||||
const objurl = URL.createObjectURL( |
|
||||||
new Blob([binary_wave], { type: 'audio/wav' }), |
|
||||||
); |
|
||||||
window.audio_cache[this.state.url] = objurl; |
|
||||||
this.setState({ |
|
||||||
state: 'loaded', |
|
||||||
data: objurl, |
|
||||||
}); |
|
||||||
}; |
|
||||||
reader.readAsBinaryString(blob); |
|
||||||
}); |
|
||||||
this.setState({ |
|
||||||
state: 'decoding', |
|
||||||
}); |
|
||||||
}); |
|
||||||
} |
|
||||||
|
|
||||||
render() { |
|
||||||
if (this.state.state === 'waiting') |
|
||||||
return ( |
|
||||||
<p> |
|
||||||
<a onClick={this.load.bind(this)}>加载音频</a> |
|
||||||
</p> |
|
||||||
); |
|
||||||
if (this.state.state === 'loading') return <p>正在下载……</p>; |
|
||||||
else if (this.state.state === 'decoding') return <p>正在解码……</p>; |
|
||||||
else if (this.state.state === 'loaded') |
|
||||||
return ( |
|
||||||
<p> |
|
||||||
<audio src={this.state.data} controls /> |
|
||||||
</p> |
|
||||||
); |
|
||||||
} |
|
||||||
} |
|
Before Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.8 KiB |
Before Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 1.4 KiB |
@ -1,47 +0,0 @@ |
|||||||
const DUMP_VER='dump_v1'; |
|
||||||
|
|
||||||
function dump() { |
|
||||||
return JSON.stringify({ |
|
||||||
_dump_ver: DUMP_VER, |
|
||||||
token: localStorage['TOKEN']||null, |
|
||||||
hole_config: localStorage['hole_config']||null, |
|
||||||
}); |
|
||||||
} |
|
||||||
function load(s) { |
|
||||||
console.log('elevator: loading',s); |
|
||||||
let obj=JSON.parse(s); |
|
||||||
if(obj._dump_ver!==DUMP_VER) { |
|
||||||
console.error('elevator: loading version mismatch, current',DUMP_VER,'param',obj._dump_ver); |
|
||||||
return; |
|
||||||
} |
|
||||||
if(localStorage['TOKEN']===undefined && obj.token) { |
|
||||||
console.log('replace token'); |
|
||||||
localStorage['TOKEN']=obj.token; |
|
||||||
} |
|
||||||
if(localStorage['hole_config']===undefined && obj.hole_config) { |
|
||||||
console.log('replace hole config'); |
|
||||||
localStorage['hole_config']=obj.hole_config; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
export function elevate() { |
|
||||||
// load
|
|
||||||
// '?foo=fo&bar=ba' -> [["foo","fo"],["bar","ba"]]
|
|
||||||
let params=window.location.search.substr(1).split('&').map((kv)=>kv.split('=')); |
|
||||||
params.forEach((kv)=>{ |
|
||||||
if(kv.length===2 && kv[0]==='_elevator_data') { |
|
||||||
load(decodeURIComponent(kv[1])); |
|
||||||
let url=new URL(window.location.href); |
|
||||||
url.search=''; |
|
||||||
window.history.replaceState('','',url.href); |
|
||||||
} |
|
||||||
}); |
|
||||||
|
|
||||||
// dump
|
|
||||||
if(window.location.protocol==='http:' && window.location.hostname==='pkuhelper.pku.edu.cn') { |
|
||||||
let url=new URL(window.location.href); |
|
||||||
url.protocol='https:'; |
|
||||||
url.search='?_elevator_data='+encodeURIComponent(dump()); |
|
||||||
window.location.replace(url.href); |
|
||||||
} |
|
||||||
} |
|