add dropdown menu and simplified the index
parent
f0c3087993
commit
a4728c7098
@ -0,0 +1,190 @@
|
|||||||
|
<html lang="en">
|
||||||
|
<style type="text/css">
|
||||||
|
body {font-family: "Old Standard TT"; font-size: 20px; line-height: 1.4; letter-spacing: 1px;}
|
||||||
|
section {margin-bottom: 50px;}
|
||||||
|
a {font-weight: bold; font-size: 24px; text-decoration: none; }
|
||||||
|
.list {
|
||||||
|
border-top: 1px solid #47505e;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
.description {
|
||||||
|
font-size: 12px;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
/* .mini-player {
|
||||||
|
background-size: 100% 100%;
|
||||||
|
background-image: url(/project/images/player.png);
|
||||||
|
cursor: pointer;
|
||||||
|
}*/
|
||||||
|
.audio-mini {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h4 align="left">woman-in-the-middle-attack</h4>
|
||||||
|
<h4 align="right">...a space for Angeliki Diakrousi to unpack</h4>
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <div style="position:absolute; top:30%; left:26%;">
|
||||||
|
<img src="thesis/carson-list.jpg"></img>
|
||||||
|
</div> -->
|
||||||
|
|
||||||
|
<div style="position:absolute; top:35%; left:41%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: tomato;" src="project/audio/leeszaal-meetings-warming.mp3"></audio>warming up @Leeszaal
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:32%; left:51%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: orange;" src="project/audio/leeszaal-meetings-choir.mp3"></audio>singing vowels @Leeszaal
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:40%; left:63%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: dodgerblue;" src="project/audio/description-alex2.mp3"></audio>describing/annotating
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:50%; left:70%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: mediumseagreen;" src="project/audio/finearts-meeting-discussion.mp3"></audio>discussing about voice in public @Fine Arts
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:62%; left:75%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: violet;" src="project/audio/leeszaal-meetings-transcribing.mp3"></audio>transcribing vowels @Leeszaal
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:75%; left:69%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: orange;" src="project/audio/finearts-meeting-choir.mp3"></audio>singing vowels @Fine Arts
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:85%; left:63%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: greenyellow;" src="project/audio/selectionB.mp3"></audio>city sounds
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:90%; left:53%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: dodgerblue;" src="project/audio/description-eugenie-CUT-SHORT.mp3"></audio>describing/annotating
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:77%; left:33%;;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: orange;" src="project/audio/finearts-meeting-choirhigh.mp3"></audio>singing vowels (high) @Fine Arts
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:53%; left:26%;;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: dodgerblue;" src="project/audio/description-lidia-CUT.mp3"></audio>describing/annotating
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div style="position:absolute; top:66%; left:28%;;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: mediumseagreen;" src="project/audio/leeszaal-meetings-discussion.mp3"></audio>discussing about voice in public @Leeszaal
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:86%; left:41%;;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: tomato;" src="project/audio/finearts-meeting-warming.mp3"></audio>warming up @Fine Arts
|
||||||
|
</div>
|
||||||
|
<div style="position:absolute; top:43%; left:32%;">
|
||||||
|
<audio controls class="audio-mini" style="background-color: violet;" src="project/audio/finearts-meeting-transcribing.mp3"></audio>transcribing vowels @Fine Arts
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.conversejs.org/4.2.0/css/converse.min.css">
|
||||||
|
<script src="https://cdn.conversejs.org/4.2.0/dist/converse.min.js" charset="utf-8"></script>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
converse.initialize({
|
||||||
|
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
|
||||||
|
show_controlbox_by_default: true
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button>
|
||||||
|
make your own podcast
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<?php
|
||||||
|
if(!is_dir("recordings")){
|
||||||
|
$res = mkdir("recordings",0777);
|
||||||
|
}
|
||||||
|
|
||||||
|
// pull the raw binary data from the POST array
|
||||||
|
$data = substr($_POST['data'], strpos($_POST['data'], ",") + 1);
|
||||||
|
$filename = urldecode($_POST['fname']);
|
||||||
|
|
||||||
|
// write the data out to the file
|
||||||
|
$fp = fopen('recordings/'.$filename, 'wb');
|
||||||
|
fwrite($fp, $decodedData);
|
||||||
|
fclose($fp);
|
||||||
|
?>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function uploadAudio(mp3Data){
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function(event){
|
||||||
|
var fd = new FormData();
|
||||||
|
var mp3Name = encodeURIComponent('audio_recording_' + new Date().getTime() + '.mp3');
|
||||||
|
console.log("mp3name = " + mp3Name);
|
||||||
|
fd.append('fname', mp3Name);
|
||||||
|
fd.append('data', event.target.result);
|
||||||
|
$.ajax({
|
||||||
|
type: 'POST',
|
||||||
|
url: 'upload.php',
|
||||||
|
data: fd,
|
||||||
|
processData: false,
|
||||||
|
contentType: false
|
||||||
|
}).done(function(data) {
|
||||||
|
//console.log(data);
|
||||||
|
log.innerHTML += "\n" + data;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(mp3Data);
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<!-- <audio controls autoplay></audio>
|
||||||
|
<script type="text/javascript" src="recorder.js"> </script>
|
||||||
|
<fieldset><legend>RECORD AUDIO</legend>
|
||||||
|
<input onclick="startRecording()" type="button" value="start recording" />
|
||||||
|
<input onclick="stopRecording()" type="button" value="stop recording and play" />
|
||||||
|
</fieldset>
|
||||||
|
<script>
|
||||||
|
var onFail = function(e) {
|
||||||
|
console.log('Rejected!', e);
|
||||||
|
};
|
||||||
|
|
||||||
|
var onSuccess = function(s) {
|
||||||
|
var context = new webkitAudioContext();
|
||||||
|
var mediaStreamSource = context.createMediaStreamSource(s);
|
||||||
|
recorder = new Recorder(mediaStreamSource);
|
||||||
|
recorder.record();
|
||||||
|
|
||||||
|
// audio loopback
|
||||||
|
// mediaStreamSource.connect(context.destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.URL = window.URL || window.webkitURL;
|
||||||
|
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;
|
||||||
|
|
||||||
|
var recorder;
|
||||||
|
var audio = document.querySelector('audio');
|
||||||
|
|
||||||
|
function startRecording() {
|
||||||
|
if (navigator.getUserMedia) {
|
||||||
|
navigator.getUserMedia({audio: true}, onSuccess, onFail);
|
||||||
|
} else {
|
||||||
|
console.log('navigator.getUserMedia not present');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function stopRecording() {
|
||||||
|
recorder.stop();
|
||||||
|
recorder.exportWAV(function(s) {
|
||||||
|
|
||||||
|
audio.src = window.URL.createObjectURL(s);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script> -->
|
||||||
|
|
||||||
|
<div>latest episode</div>
|
||||||
|
<?php
|
||||||
|
//insert the folder HERE
|
||||||
|
$files = scandir("project/podcasts", SCANDIR_SORT_DESCENDING);
|
||||||
|
$newest_file = $files[0];
|
||||||
|
echo "<audio controls src='project/podcasts/$newest_file'></audio>";
|
||||||
|
?>
|
||||||
|
|
||||||
|
<div>You can send me a message here angeliki@conversations.im</div>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
@ -0,0 +1,8 @@
|
|||||||
|
from pydub import AudioSegment
|
||||||
|
from pydub.utils import mediainfo
|
||||||
|
|
||||||
|
print (mediainfo("podcasts/3_podcast.mp3"))
|
||||||
|
|
||||||
|
# sound= AudioSegment.from_file("podcasts/3_podcast.mp3", format="mp3")
|
||||||
|
# file=sound.export("out.mp3", tags={"podcaster":"lain"})
|
||||||
|
# print (mediainfo("out.mp3"))
|
@ -0,0 +1,221 @@
|
|||||||
|
(function(window){
|
||||||
|
|
||||||
|
var WORKER_PATH = 'recorderWorker.js';
|
||||||
|
var Recorder = function(source, cfg){
|
||||||
|
var config = cfg || {};
|
||||||
|
var bufferLen = config.bufferLen || 4096;
|
||||||
|
this.context = source.context;
|
||||||
|
this.node = this.context.createScriptProcessor(bufferLen, 2, 2);
|
||||||
|
var worker = new Worker(config.workerPath || WORKER_PATH);
|
||||||
|
worker.postMessage({
|
||||||
|
command: 'init',
|
||||||
|
config: {
|
||||||
|
sampleRate: this.context.sampleRate
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var recording = false,
|
||||||
|
currCallback;
|
||||||
|
|
||||||
|
this.node.onaudioprocess = function(e){
|
||||||
|
if (!recording) return;
|
||||||
|
worker.postMessage({
|
||||||
|
command: 'record',
|
||||||
|
buffer: [
|
||||||
|
e.inputBuffer.getChannelData(0),
|
||||||
|
e.inputBuffer.getChannelData(1)
|
||||||
|
]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.configure = function(cfg){
|
||||||
|
for (var prop in cfg){
|
||||||
|
if (cfg.hasOwnProperty(prop)){
|
||||||
|
config[prop] = cfg[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.record = function(){
|
||||||
|
|
||||||
|
recording = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stop = function(){
|
||||||
|
|
||||||
|
recording = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.clear = function(){
|
||||||
|
worker.postMessage({ command: 'clear' });
|
||||||
|
}
|
||||||
|
|
||||||
|
this.getBuffer = function(cb) {
|
||||||
|
currCallback = cb || config.callback;
|
||||||
|
worker.postMessage({ command: 'getBuffer' })
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exportWAV = function(cb, type){
|
||||||
|
currCallback = cb || config.callback;
|
||||||
|
type = type || config.type || 'audio/wav';
|
||||||
|
if (!currCallback) throw new Error('Callback not set');
|
||||||
|
worker.postMessage({
|
||||||
|
command: 'exportWAV',
|
||||||
|
type: type
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
worker.onmessage = function(e){
|
||||||
|
var blob = e.data;
|
||||||
|
currCallback(blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
source.connect(this.node);
|
||||||
|
this.node.connect(this.context.destination); //this should not be necessary
|
||||||
|
};
|
||||||
|
|
||||||
|
Recorder.forceDownload = function(blob, filename){
|
||||||
|
var url = (window.URL || window.webkitURL).createObjectURL(blob);
|
||||||
|
var link = window.document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = filename || 'output.wav';
|
||||||
|
var click = document.createEvent("Event");
|
||||||
|
click.initEvent("click", true, true);
|
||||||
|
link.dispatchEvent(click);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.Recorder = Recorder;
|
||||||
|
|
||||||
|
})(window);
|
||||||
|
|
||||||
|
//ADDITIONAL JS recorderWorker.js
|
||||||
|
var recLength = 0,
|
||||||
|
recBuffersL = [],
|
||||||
|
recBuffersR = [],
|
||||||
|
sampleRate;
|
||||||
|
this.onmessage = function(e){
|
||||||
|
switch(e.data.command){
|
||||||
|
case 'init':
|
||||||
|
init(e.data.config);
|
||||||
|
break;
|
||||||
|
case 'record':
|
||||||
|
record(e.data.buffer);
|
||||||
|
break;
|
||||||
|
case 'exportWAV':
|
||||||
|
exportWAV(e.data.type);
|
||||||
|
break;
|
||||||
|
case 'getBuffer':
|
||||||
|
getBuffer();
|
||||||
|
break;
|
||||||
|
case 'clear':
|
||||||
|
clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(config){
|
||||||
|
sampleRate = config.sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
function record(inputBuffer){
|
||||||
|
|
||||||
|
recBuffersL.push(inputBuffer[0]);
|
||||||
|
recBuffersR.push(inputBuffer[1]);
|
||||||
|
recLength += inputBuffer[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportWAV(type){
|
||||||
|
var bufferL = mergeBuffers(recBuffersL, recLength);
|
||||||
|
var bufferR = mergeBuffers(recBuffersR, recLength);
|
||||||
|
var interleaved = interleave(bufferL, bufferR);
|
||||||
|
var dataview = encodeWAV(interleaved);
|
||||||
|
var audioBlob = new Blob([dataview], { type: type });
|
||||||
|
|
||||||
|
this.postMessage(audioBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuffer() {
|
||||||
|
var buffers = [];
|
||||||
|
buffers.push( mergeBuffers(recBuffersL, recLength) );
|
||||||
|
buffers.push( mergeBuffers(recBuffersR, recLength) );
|
||||||
|
this.postMessage(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear(){
|
||||||
|
recLength = 0;
|
||||||
|
recBuffersL = [];
|
||||||
|
recBuffersR = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeBuffers(recBuffers, recLength){
|
||||||
|
var result = new Float32Array(recLength);
|
||||||
|
var offset = 0;
|
||||||
|
for (var i = 0; i < recBuffers.length; i++){
|
||||||
|
result.set(recBuffers[i], offset);
|
||||||
|
offset += recBuffers[i].length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function interleave(inputL, inputR){
|
||||||
|
var length = inputL.length + inputR.length;
|
||||||
|
var result = new Float32Array(length);
|
||||||
|
|
||||||
|
var index = 0,
|
||||||
|
inputIndex = 0;
|
||||||
|
|
||||||
|
while (index < length){
|
||||||
|
result[index++] = inputL[inputIndex];
|
||||||
|
result[index++] = inputR[inputIndex];
|
||||||
|
inputIndex++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function floatTo16BitPCM(output, offset, input){
|
||||||
|
for (var i = 0; i < input.length; i++, offset+=2){
|
||||||
|
var s = Math.max(-1, Math.min(1, input[i]));
|
||||||
|
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeString(view, offset, string){
|
||||||
|
for (var i = 0; i < string.length; i++){
|
||||||
|
view.setUint8(offset + i, string.charCodeAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeWAV(samples){
|
||||||
|
var buffer = new ArrayBuffer(44 + samples.length * 2);
|
||||||
|
var view = new DataView(buffer);
|
||||||
|
|
||||||
|
/* RIFF identifier */
|
||||||
|
writeString(view, 0, 'RIFF');
|
||||||
|
/* file length */
|
||||||
|
view.setUint32(4, 32 + samples.length * 2, true);
|
||||||
|
/* RIFF type */
|
||||||
|
writeString(view, 8, 'WAVE');
|
||||||
|
/* format chunk identifier */
|
||||||
|
writeString(view, 12, 'fmt ');
|
||||||
|
/* format chunk length */
|
||||||
|
view.setUint32(16, 16, true);
|
||||||
|
/* sample format (raw) */
|
||||||
|
view.setUint16(20, 1, true);
|
||||||
|
/* channel count */
|
||||||
|
view.setUint16(22, 2, true);
|
||||||
|
/* sample rate */
|
||||||
|
view.setUint32(24, sampleRate, true);
|
||||||
|
/* byte rate (sample rate * block align) */
|
||||||
|
view.setUint32(28, sampleRate * 4, true);
|
||||||
|
/* block align (channel count * bytes per sample) */
|
||||||
|
view.setUint16(32, 4, true);
|
||||||
|
/* bits per sample */
|
||||||
|
view.setUint16(34, 16, true);
|
||||||
|
/* data chunk identifier */
|
||||||
|
writeString(view, 36, 'data');
|
||||||
|
/* data chunk length */
|
||||||
|
view.setUint32(40, samples.length * 2, true);
|
||||||
|
|
||||||
|
floatTo16BitPCM(view, 44, samples);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
@ -0,0 +1,161 @@
|
|||||||
|
/*License (MIT)
|
||||||
|
|
||||||
|
Copyright © 2013 Matt Diamond
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var recLength = 0,
|
||||||
|
recBuffersL = [],
|
||||||
|
recBuffersR = [],
|
||||||
|
sampleRate;
|
||||||
|
|
||||||
|
this.onmessage = function(e){
|
||||||
|
switch(e.data.command){
|
||||||
|
case 'init':
|
||||||
|
init(e.data.config);
|
||||||
|
break;
|
||||||
|
case 'record':
|
||||||
|
record(e.data.buffer);
|
||||||
|
break;
|
||||||
|
case 'exportWAV':
|
||||||
|
exportWAV(e.data.type);
|
||||||
|
break;
|
||||||
|
case 'exportMonoWAV':
|
||||||
|
exportMonoWAV(e.data.type);
|
||||||
|
break;
|
||||||
|
case 'getBuffers':
|
||||||
|
getBuffers();
|
||||||
|
break;
|
||||||
|
case 'clear':
|
||||||
|
clear();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function init(config){
|
||||||
|
sampleRate = config.sampleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
function record(inputBuffer){
|
||||||
|
recBuffersL.push(inputBuffer[0]);
|
||||||
|
recBuffersR.push(inputBuffer[1]);
|
||||||
|
recLength += inputBuffer[0].length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportWAV(type){
|
||||||
|
var bufferL = mergeBuffers(recBuffersL, recLength);
|
||||||
|
var bufferR = mergeBuffers(recBuffersR, recLength);
|
||||||
|
var interleaved = interleave(bufferL, bufferR);
|
||||||
|
var dataview = encodeWAV(interleaved);
|
||||||
|
var audioBlob = new Blob([dataview], { type: type });
|
||||||
|
|
||||||
|
this.postMessage(audioBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportMonoWAV(type){
|
||||||
|
var bufferL = mergeBuffers(recBuffersL, recLength);
|
||||||
|
var dataview = encodeWAV(bufferL, true);
|
||||||
|
var audioBlob = new Blob([dataview], { type: type });
|
||||||
|
|
||||||
|
this.postMessage(audioBlob);
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBuffers() {
|
||||||
|
var buffers = [];
|
||||||
|
buffers.push( mergeBuffers(recBuffersL, recLength) );
|
||||||
|
buffers.push( mergeBuffers(recBuffersR, recLength) );
|
||||||
|
this.postMessage(buffers);
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear(){
|
||||||
|
recLength = 0;
|
||||||
|
recBuffersL = [];
|
||||||
|
recBuffersR = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
function mergeBuffers(recBuffers, recLength){
|
||||||
|
var result = new Float32Array(recLength);
|
||||||
|
var offset = 0;
|
||||||
|
for (var i = 0; i < recBuffers.length; i++){
|
||||||
|
result.set(recBuffers[i], offset);
|
||||||
|
offset += recBuffers[i].length;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function interleave(inputL, inputR){
|
||||||
|
var length = inputL.length + inputR.length;
|
||||||
|
var result = new Float32Array(length);
|
||||||
|
|
||||||
|
var index = 0,
|
||||||
|
inputIndex = 0;
|
||||||
|
|
||||||
|
while (index < length){
|
||||||
|
result[index++] = inputL[inputIndex];
|
||||||
|
result[index++] = inputR[inputIndex];
|
||||||
|
inputIndex++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function floatTo16BitPCM(output, offset, input){
|
||||||
|
for (var i = 0; i < input.length; i++, offset+=2){
|
||||||
|
var s = Math.max(-1, Math.min(1, input[i]));
|
||||||
|
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function writeString(view, offset, string){
|
||||||
|
for (var i = 0; i < string.length; i++){
|
||||||
|
view.setUint8(offset + i, string.charCodeAt(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function encodeWAV(samples, mono){
|
||||||
|
var buffer = new ArrayBuffer(44 + samples.length * 2);
|
||||||
|
var view = new DataView(buffer);
|
||||||
|
|
||||||
|
/* RIFF identifier */
|
||||||
|
writeString(view, 0, 'RIFF');
|
||||||
|
/* file length */
|
||||||
|
view.setUint32(4, 32 + samples.length * 2, true);
|
||||||
|
/* RIFF type */
|
||||||
|
writeString(view, 8, 'WAVE');
|
||||||
|
/* format chunk identifier */
|
||||||
|
writeString(view, 12, 'fmt ');
|
||||||
|
/* format chunk length */
|
||||||
|
view.setUint32(16, 16, true);
|
||||||
|
/* sample format (raw) */
|
||||||
|
view.setUint16(20, 1, true);
|
||||||
|
/* channel count */
|
||||||
|
view.setUint16(22, mono?1:2, true);
|
||||||
|
/* sample rate */
|
||||||
|
view.setUint32(24, sampleRate, true);
|
||||||
|
/* byte rate (sample rate * block align) */
|
||||||
|
view.setUint32(28, sampleRate * 4, true);
|
||||||
|
/* block align (channel count * bytes per sample) */
|
||||||
|
view.setUint16(32, 4, true);
|
||||||
|
/* bits per sample */
|
||||||
|
view.setUint16(34, 16, true);
|
||||||
|
/* data chunk identifier */
|
||||||
|
writeString(view, 36, 'data');
|
||||||
|
/* data chunk length */
|
||||||
|
view.setUint32(40, samples.length * 2, true);
|
||||||
|
|
||||||
|
floatTo16BitPCM(view, 44, samples);
|
||||||
|
|
||||||
|
return view;
|
||||||
|
}
|
Loading…
Reference in New Issue