mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 19:51:51 +09:00
mp3 decoding but slow
This commit is contained in:
@@ -1,150 +0,0 @@
|
||||
const Mp3 = require('mp3dec')
|
||||
const pcm = require("pcm")
|
||||
|
||||
|
||||
class SequentialFileBuffer {
|
||||
|
||||
constructor(path, offset, length) {
|
||||
if (Array.isArray(path)) throw Error("arg #1 is path(string), not array")
|
||||
|
||||
this.path = path
|
||||
this.file = files.open(path)
|
||||
|
||||
this.offset = offset || 0
|
||||
this.originalOffset = offset
|
||||
this.length = length || this.file.size
|
||||
|
||||
this.seq = require("seqread")
|
||||
this.seq.prepare(path)
|
||||
}
|
||||
|
||||
/*readFull(n) {
|
||||
throw Error()
|
||||
let ptr = this.seq.readBytes(n)
|
||||
return ptr
|
||||
}*/
|
||||
|
||||
readStr(n) {
|
||||
let ptr = this.seq.readBytes(n)
|
||||
let s = ''
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (i >= this.length) break
|
||||
s += String.fromCharCode(sys.peek(ptr + i))
|
||||
}
|
||||
sys.free(ptr)
|
||||
return s
|
||||
}
|
||||
|
||||
readByteNumbers(n) {
|
||||
let ptr = this.seq.readBytes(n)
|
||||
let s = []
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (i >= this.length) break
|
||||
s.push(sys.peek(ptr + i))
|
||||
}
|
||||
sys.free(ptr)
|
||||
return s
|
||||
}
|
||||
|
||||
unread(diff) {
|
||||
let newSkipLen = this.seq.getReadCount() - diff
|
||||
this.seq.prepare(this.path)
|
||||
this.seq.skip(newSkipLen)
|
||||
}
|
||||
|
||||
rewind() {
|
||||
this.seq.prepare(this.path)
|
||||
}
|
||||
|
||||
seek(p) {
|
||||
this.seq.prepare(this.path)
|
||||
this.seq.skip(p)
|
||||
}
|
||||
|
||||
get byteLength() {
|
||||
return this.length
|
||||
}
|
||||
|
||||
/*get remaining() {
|
||||
return this.length - this.getReadCount()
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
Object.keys(Mp3).forEach(e=>{
|
||||
print(`${e}\t`)
|
||||
})
|
||||
println()
|
||||
|
||||
println("reading...")
|
||||
//let arr = files.open("A:/gateless.mp3").bread()
|
||||
//let ab = new ArrayBuffer(arr.length)
|
||||
//let abba = new Uint8Array(ab)
|
||||
//arr.forEach((v,i)=>{ abba[i] = v })
|
||||
//let mp3ArrayBuffer = new Uint8Array(ab, 0, arr.length)*
|
||||
|
||||
println("decoding...")
|
||||
let decoder = Mp3.newDecoder(new SequentialFileBuffer("A:/gateless0.mp3"))
|
||||
if (decoder === null) throw Error("decoder is null")
|
||||
|
||||
audio.resetParams(0)
|
||||
audio.purgeQueue(0)
|
||||
audio.setPcmMode(0)
|
||||
audio.setMasterVolume(0, 255)
|
||||
audio.play(0)
|
||||
|
||||
let decodedLength = 0
|
||||
let readPtr = sys.malloc(8000)
|
||||
let decodePtr = sys.malloc(12000)
|
||||
|
||||
|
||||
function decodeAndResample(readArr, decodePtr, readLength) {
|
||||
for (let i = 0; i < readLength; i+= 2) {
|
||||
let sample = pcm.u16Tos16(readArr[i] | (readArr[i+1] << 8))
|
||||
let u8 = pcm.s16Tou8(sample)
|
||||
|
||||
sys.poke(decodePtr + (i >> 1), u8)
|
||||
}
|
||||
return readLength / 2
|
||||
}
|
||||
|
||||
|
||||
function printPlayBar() {
|
||||
}
|
||||
|
||||
|
||||
const QUEUE_MAX = 4
|
||||
let t1 = sys.nanoTime()
|
||||
decoder.decode(obj=>{
|
||||
let t2 = sys.nanoTime()
|
||||
|
||||
|
||||
let buf = obj.buf
|
||||
let err = obj.err
|
||||
|
||||
decodedLength += buf.byteLength
|
||||
|
||||
let declen = decodeAndResample(buf, decodePtr, buf.byteLength)
|
||||
|
||||
audio.putPcmDataByPtr(decodePtr, declen, 0)
|
||||
audio.setSampleUploadLength(0, declen)
|
||||
audio.startSampleUpload(0)
|
||||
audio.play(0)
|
||||
|
||||
|
||||
// sys.sleep(10) // decoding time is slower than realtime :(
|
||||
|
||||
|
||||
let decodingTime = t2 - t1
|
||||
let bufRealTimeLen = (declen) / 64000.0 * 1000000000
|
||||
t1 = t2
|
||||
println(`Decoded ${decodedLength} bytes; lag: ${(decodingTime - bufRealTimeLen) / 1000000} ms`)
|
||||
|
||||
|
||||
|
||||
|
||||
}) // now you got decoded PCM data
|
||||
|
||||
sys.free(readPtr)
|
||||
sys.free(decodePtr)
|
||||
@@ -145,5 +145,5 @@ while (sampleSize > 0) {
|
||||
sys.sleep(10)
|
||||
}
|
||||
|
||||
audio.stop(0)
|
||||
//audio.stop(0)
|
||||
sys.free(decodePtr)
|
||||
|
||||
@@ -348,6 +348,13 @@ shell.resolvePathInput = function(input) {
|
||||
|
||||
return { string: pathstr, pwd: newPwd, drive: driveLetter, full: `${driveLetter}:${pathstr}` }
|
||||
}
|
||||
shell.isValidDriveLetter = function(l) {
|
||||
if (typeof l === 'string' || l instanceof String) {
|
||||
let lc = l.charCodeAt(0)
|
||||
return (l == '$' || 65 <= lc && lc <= 90 || 97 <= lc && lc <= 122)
|
||||
}
|
||||
else return false
|
||||
}
|
||||
shell.coreutils = {
|
||||
/* Args follow this format:
|
||||
* <command-name> <1st arg> <2nd arg> ...
|
||||
@@ -682,30 +689,39 @@ shell.execute = function(line) {
|
||||
// search through PATH for execution
|
||||
|
||||
var fileExists = false
|
||||
var searchDir = (cmd.startsWith("/")) ? [""] : ["/"+shell_pwd.join("/")].concat(_TVDOS.getPath())
|
||||
var searchFile;
|
||||
var searchPath = "";
|
||||
|
||||
var pathExt = [] // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
|
||||
// fill pathExt using %PATHEXT% but also capitalise them
|
||||
if (cmd.split(".")[1] === undefined)
|
||||
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); })
|
||||
else
|
||||
pathExt.push("") // final empty extension
|
||||
// if the file is absolute path:
|
||||
if (shell.isValidDriveLetter(cmd[0]) && cmd[1] == ':') {
|
||||
searchFile = files.open(cmd)
|
||||
searchPath = trimStartRevSlash(searchFile.path)
|
||||
fileExists = searchFile.exists
|
||||
}
|
||||
// else
|
||||
else {
|
||||
var searchDir = (cmd.startsWith("/")) ? [""] : ["/"+shell_pwd.join("/")].concat(_TVDOS.getPath())
|
||||
|
||||
let searchPath = ""
|
||||
let searchFile = 0
|
||||
var pathExt = [] // it seems Nashorn does not like 'let' too much? this line gets ignored sometimes
|
||||
// fill pathExt using %PATHEXT% but also capitalise them
|
||||
if (cmd.split(".")[1] === undefined)
|
||||
_TVDOS.variables.PATHEXT.split(';').forEach(function(it) { pathExt.push(it); pathExt.push(it.toUpperCase()); })
|
||||
else
|
||||
pathExt.push("") // final empty extension
|
||||
|
||||
searchLoop:
|
||||
for (var i = 0; i < searchDir.length; i++) {
|
||||
for (var j = 0; j < pathExt.length; j++) {
|
||||
let search = searchDir[i]; if (!search.endsWith('\\')) search += '\\'
|
||||
searchPath = trimStartRevSlash(search + cmd + pathExt[j])
|
||||
searchLoop:
|
||||
for (var i = 0; i < searchDir.length; i++) {
|
||||
for (var j = 0; j < pathExt.length; j++) {
|
||||
let search = searchDir[i]; if (!search.endsWith('\\')) search += '\\'
|
||||
searchPath = trimStartRevSlash(search + cmd + pathExt[j])
|
||||
|
||||
// debugprintln("[shell.execute] file search path: "+searchPath)
|
||||
// debugprintln("[shell.execute] file search path: "+searchPath)
|
||||
|
||||
searchFile = files.open(`${CURRENT_DRIVE}:\\${searchPath}`)
|
||||
if (searchFile.exists) {
|
||||
fileExists = true
|
||||
break searchLoop
|
||||
searchFile = files.open(`${CURRENT_DRIVE}:\\${searchPath}`)
|
||||
if (searchFile.exists) {
|
||||
fileExists = true
|
||||
break searchLoop
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,7 +247,7 @@ while (!stopPlay && seqread.getReadCount() < FILE_LENGTH) {
|
||||
let endTime = sys.nanoTime()
|
||||
|
||||
sys.free(ipfbuf)
|
||||
audio.stop(0)
|
||||
//audio.stop(0)
|
||||
|
||||
let timeTook = (endTime - startTime) / 1000000000.0
|
||||
|
||||
|
||||
227
assets/disk0/tvdos/bin/playmp3.js
Normal file
227
assets/disk0/tvdos/bin/playmp3.js
Normal file
@@ -0,0 +1,227 @@
|
||||
const Mp3 = require('mp3dec')
|
||||
const pcm = require("pcm")
|
||||
const interactive = exec_args[2] && exec_args[2].toLowerCase() == "/i"
|
||||
|
||||
function printdbg(s) { if (0) serial.println(s) }
|
||||
|
||||
class SequentialFileBuffer {
|
||||
|
||||
constructor(path, offset, length) {
|
||||
if (Array.isArray(path)) throw Error("arg #1 is path(string), not array")
|
||||
|
||||
this.path = path
|
||||
this.file = files.open(path)
|
||||
|
||||
this.offset = offset || 0
|
||||
this.originalOffset = offset
|
||||
this.length = length || this.file.size
|
||||
|
||||
this.seq = require("seqread")
|
||||
this.seq.prepare(path)
|
||||
}
|
||||
|
||||
/*readFull(n) {
|
||||
throw Error()
|
||||
let ptr = this.seq.readBytes(n)
|
||||
return ptr
|
||||
}*/
|
||||
|
||||
readStr(n) {
|
||||
let ptr = this.seq.readBytes(n)
|
||||
let s = ''
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (i >= this.length) break
|
||||
s += String.fromCharCode(sys.peek(ptr + i))
|
||||
}
|
||||
sys.free(ptr)
|
||||
return s
|
||||
}
|
||||
|
||||
readByteNumbers(n) {
|
||||
let ptr = this.seq.readBytes(n)
|
||||
try {
|
||||
let s = []
|
||||
for (let i = 0; i < n; i++) {
|
||||
if (i >= this.length) break
|
||||
s.push(sys.peek(ptr + i))
|
||||
}
|
||||
sys.free(ptr)
|
||||
return s
|
||||
}
|
||||
catch (e) {
|
||||
println(`n: ${n}; ptr: ${ptr}`)
|
||||
println(e)
|
||||
}
|
||||
}
|
||||
|
||||
unread(diff) {
|
||||
let newSkipLen = this.seq.getReadCount() - diff
|
||||
this.seq.prepare(this.path)
|
||||
this.seq.skip(newSkipLen)
|
||||
}
|
||||
|
||||
rewind() {
|
||||
this.seq.prepare(this.path)
|
||||
}
|
||||
|
||||
seek(p) {
|
||||
this.seq.prepare(this.path)
|
||||
this.seq.skip(p)
|
||||
}
|
||||
|
||||
get byteLength() {
|
||||
return this.length
|
||||
}
|
||||
|
||||
/*get remaining() {
|
||||
return this.length - this.getReadCount()
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
con.curs_set(0)
|
||||
let [cy, cx] = con.getyx()
|
||||
let [__, CONSOLE_WIDTH] = con.getmaxyx()
|
||||
let paintWidth = CONSOLE_WIDTH - 16
|
||||
if (interactive) {
|
||||
println("Decoding...")
|
||||
}
|
||||
|
||||
|
||||
printdbg("pre-decode...")
|
||||
let filebuf = new SequentialFileBuffer(_G.shell.resolvePathInput(exec_args[1]).full)
|
||||
const FILE_SIZE = filebuf.length
|
||||
let decoder = Mp3.newDecoder(filebuf)
|
||||
if (decoder === null) throw Error("decoder is null")
|
||||
|
||||
const HEADER_SIZE = decoder.headerSize + 3
|
||||
const FRAME_SIZE = decoder.frameSize // only works reliably for CBR
|
||||
|
||||
//serial.println(`header size: ${HEADER_SIZE}`)
|
||||
//serial.println(`frame size: ${FRAME_SIZE}`)
|
||||
|
||||
audio.resetParams(0)
|
||||
audio.purgeQueue(0)
|
||||
audio.setPcmMode(0)
|
||||
audio.setPcmQueueCapacityIndex(0, 5) // queue size is now 24
|
||||
const QUEUE_MAX = audio.getPcmQueueCapacity(0)
|
||||
audio.setMasterVolume(0, 255)
|
||||
audio.play(0)
|
||||
|
||||
let decodedLength = 0
|
||||
let readPtr = sys.malloc(8000)
|
||||
let decodePtr = sys.malloc(12000)
|
||||
|
||||
function bytesToSec(i) {
|
||||
// using fixed value: FRAME_SIZE(216) bytes for 36 ms on sampling rate 32000 Hz
|
||||
return i / (FRAME_SIZE * 1000 / bufRealTimeLen)
|
||||
}
|
||||
function secToReadable(n) {
|
||||
let mins = ''+((n/60)|0)
|
||||
let secs = ''+(n % 60)
|
||||
return `${mins.padStart(2,'0')}:${secs.padStart(2,'0')}`
|
||||
}
|
||||
function decodeAndResample(inPtr, outPtr, inputLen) {
|
||||
// TODO resample
|
||||
for (let k = 0; k < inputLen / 2; k+=2) {
|
||||
let sample = [
|
||||
pcm.u16Tos16(sys.peek(inPtr + k*2 + 0) | (sys.peek(inPtr + k*2 + 1) << 8)),
|
||||
pcm.u16Tos16(sys.peek(inPtr + k*2 + 2) | (sys.peek(inPtr + k*2 + 3) << 8))
|
||||
]
|
||||
sys.poke(outPtr + k, pcm.s16Tou8(sample[0]))
|
||||
sys.poke(outPtr + k + 1, pcm.s16Tou8(sample[1]))
|
||||
// soothing visualiser(????)
|
||||
// printvis(`${sampleToVisual(sample[0])} | ${sampleToVisual(sample[1])}`)
|
||||
}
|
||||
return inputLen / 2
|
||||
}
|
||||
|
||||
|
||||
function printPlayBar() {
|
||||
}
|
||||
|
||||
let stopPlay = false
|
||||
con.curs_set(0)
|
||||
if (interactive) {
|
||||
con.move(cy, cy)
|
||||
println("Push and hold Backspace to exit")
|
||||
}
|
||||
[cy, cx] = con.getyx()
|
||||
function printPlayBar(currently) {
|
||||
if (interactive) {
|
||||
// let currently = decodedLength
|
||||
let total = FILE_SIZE - HEADER_SIZE
|
||||
|
||||
let currentlySec = Math.round(bytesToSec(currently))
|
||||
let totalSec = Math.round(bytesToSec(total))
|
||||
|
||||
con.move(cy, 1)
|
||||
print(' '.repeat(15))
|
||||
con.move(cy, 1)
|
||||
|
||||
print(`${secToReadable(currentlySec)} / ${secToReadable(totalSec)}`)
|
||||
|
||||
con.move(cy, 15)
|
||||
print(' ')
|
||||
let progressbar = '\x84205u'.repeat(paintWidth + 1)
|
||||
print(progressbar)
|
||||
|
||||
con.mvaddch(cy, 16 + Math.round(paintWidth * (currently / total)), 0xDB)
|
||||
}
|
||||
}
|
||||
let t1 = sys.nanoTime()
|
||||
let bufRealTimeLen = 36
|
||||
try {
|
||||
decoder.decode((ptr, len, pos)=>{
|
||||
|
||||
if (interactive) {
|
||||
sys.poke(-40, 1)
|
||||
if (sys.peek(-41) == 67) {
|
||||
stopPlay = true
|
||||
throw "STOP"
|
||||
}
|
||||
}
|
||||
|
||||
printPlayBar(pos)
|
||||
|
||||
let t2 = sys.nanoTime()
|
||||
|
||||
decodedLength += len
|
||||
|
||||
// serial.println(`Audio queue size: ${audio.getPosition(0)}/${QUEUE_MAX}`)
|
||||
|
||||
if (audio.getPosition(0) >= QUEUE_MAX) {
|
||||
while (audio.getPosition(0) >= (QUEUE_MAX >>> 1)) {
|
||||
printdbg(`Queue full, waiting until the queue has some space (${audio.getPosition(0)}/${QUEUE_MAX})`)
|
||||
// serial.println(`Queue full, waiting until the queue has some space (${audio.getPosition(0)}/${QUEUE_MAX})`)
|
||||
sys.sleep(bufRealTimeLen)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
let declen = decodeAndResample(ptr, decodePtr, len)
|
||||
|
||||
audio.putPcmDataByPtr(decodePtr, declen, 0)
|
||||
audio.setSampleUploadLength(0, declen)
|
||||
audio.startSampleUpload(0)
|
||||
|
||||
|
||||
let decodingTime = (t2 - t1) / 1000000.0
|
||||
bufRealTimeLen = (declen) / 64000.0 * 1000
|
||||
t1 = t2
|
||||
|
||||
printdbg(`Decoded ${decodedLength} bytes; target: ${bufRealTimeLen} ms, lag: ${decodingTime - bufRealTimeLen} ms`)
|
||||
|
||||
|
||||
}) // now you got decoded PCM data
|
||||
}
|
||||
catch (e) {
|
||||
if (e != "STOP") throw e
|
||||
}
|
||||
finally {
|
||||
//audio.stop(0)
|
||||
sys.free(readPtr)
|
||||
sys.free(decodePtr)
|
||||
}
|
||||
@@ -86,10 +86,10 @@ audio.setMasterVolume(0, 255)
|
||||
|
||||
let readLength = 1
|
||||
|
||||
function printPlayBar(startOffset) {
|
||||
function printPlayBar() {
|
||||
if (interactive) {
|
||||
let currently = seqread.getReadCount() - startOffset
|
||||
let total = FILE_SIZE - startOffset - 8
|
||||
let currently = seqread.getReadCount()
|
||||
let total = FILE_SIZE
|
||||
|
||||
let currentlySec = Math.round(bytesToSec(currently))
|
||||
let totalSec = Math.round(bytesToSec(total))
|
||||
@@ -157,6 +157,6 @@ while (!stopPlay && seqread.getReadCount() < FILE_SIZE && readLength > 0) {
|
||||
}
|
||||
|
||||
|
||||
audio.stop(0)
|
||||
//audio.stop(0)
|
||||
if (readPtr !== undefined) sys.free(readPtr)
|
||||
if (decodePtr !== undefined) sys.free(decodePtr)
|
||||
|
||||
@@ -268,6 +268,6 @@ while (!stopPlay && seqread.getReadCount() < FILE_SIZE - 8) {
|
||||
sys.spin()
|
||||
}
|
||||
|
||||
audio.stop(0)
|
||||
//audio.stop(0)
|
||||
if (readPtr !== undefined) sys.free(readPtr)
|
||||
if (decodePtr !== undefined) sys.free(decodePtr)
|
||||
|
||||
@@ -198,12 +198,14 @@ var Frame = {
|
||||
*/
|
||||
frame.decode = function () {
|
||||
var nch = frame.header.numberOfChannels();
|
||||
var out;
|
||||
var out_ptr;
|
||||
var out_ptr_len;
|
||||
if (nch === 1) {
|
||||
out = new Uint8Array(consts.BytesPerFrame / 2);
|
||||
out_ptr_len = consts.BytesPerFrame / 2
|
||||
} else {
|
||||
out = new Uint8Array(consts.BytesPerFrame);
|
||||
out_ptr_len = consts.BytesPerFrame
|
||||
}
|
||||
out_ptr = sys.malloc(out_ptr_len);
|
||||
for (var gr = 0; gr < 2; gr++) {
|
||||
for (var ch = 0; ch < nch; ch++) {
|
||||
frame.requantize(gr, ch);
|
||||
@@ -212,16 +214,21 @@ var Frame = {
|
||||
frame.stereo(gr);
|
||||
for (var ch = 0; ch < nch; ch++) {
|
||||
frame.antialias(gr, ch);
|
||||
frame.hybridSynthesis(gr, ch);
|
||||
|
||||
audio.mp3_hybridSynthesis(frame.sideInfo, frame.mainData.Is, frame.store[ch], gr, ch)
|
||||
//frame.hybridSynthesis(gr, ch);
|
||||
|
||||
frame.frequencyInversion(gr, ch);
|
||||
if (nch === 1) {
|
||||
frame.subbandSynthesis(gr, ch, out.subarray(consts.SamplesPerGr * 4 * gr / 2));
|
||||
audio.mp3_subbandSynthesis(nch, frame, gr, ch, out_ptr + (consts.SamplesPerGr * 4 * gr / 2))
|
||||
//frame.subbandSynthesis(gr, ch, out_ptr + (consts.SamplesPerGr * 4 * gr / 2));
|
||||
} else {
|
||||
frame.subbandSynthesis(gr, ch, out.subarray(consts.SamplesPerGr * 4 * gr));
|
||||
audio.mp3_subbandSynthesis(nch, frame, gr, ch, out_ptr + (consts.SamplesPerGr * 4 * gr))
|
||||
//frame.subbandSynthesis(gr, ch, out_ptr + (consts.SamplesPerGr * 4 * gr));
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return [out_ptr, out_ptr_len];
|
||||
};
|
||||
|
||||
frame.antialias = function (gr, ch) {
|
||||
@@ -433,7 +440,7 @@ var Frame = {
|
||||
var win_len = consts.SfBandIndicesSet[sfreq].S[sfb + 1] -
|
||||
consts.SfBandIndicesSet[sfreq].S[sfb];
|
||||
|
||||
for (var i = 36; i < int(f.sideInfo.Count1[gr][ch]);) /* i++ done below! */ {
|
||||
for (var i = 36; i < int(frame.sideInfo.Count1[gr][ch]);) /* i++ done below! */ {
|
||||
// Check if we're into the next scalefac band
|
||||
if (i === next_sfb) {
|
||||
sfb++;
|
||||
@@ -573,7 +580,7 @@ var Frame = {
|
||||
}
|
||||
};
|
||||
|
||||
frame.subbandSynthesis = function (gr, ch, out) {
|
||||
frame.subbandSynthesis = function (gr, ch, out_ptr) {
|
||||
var u_vec = new Float32Array(512);
|
||||
var s_vec = new Float32Array(32);
|
||||
|
||||
@@ -616,7 +623,7 @@ var Frame = {
|
||||
} else if (samp < -32767) {
|
||||
samp = -32767;
|
||||
}
|
||||
var s = samp;
|
||||
var s = samp|0;
|
||||
var idx;
|
||||
if (nch === 1) {
|
||||
idx = 2 * (32*ss + i);
|
||||
@@ -624,15 +631,19 @@ var Frame = {
|
||||
idx = 4 * (32*ss + i);
|
||||
}
|
||||
if (ch === 0) {
|
||||
out[idx] = s;
|
||||
out[idx + 1] = (s >>> 8) >>> 0;
|
||||
// out[idx] = s;
|
||||
// out[idx + 1] = (s >>> 8) >>> 0;
|
||||
sys.poke(out_ptr + idx, s)
|
||||
sys.poke(out_ptr + idx + 1, (s >>> 8) >>> 0)
|
||||
} else {
|
||||
out[idx + 2] = s;
|
||||
out[idx + 3] = (s >>> 8) >>> 0;
|
||||
// out[idx + 2] = s;
|
||||
// out[idx + 3] = (s >>> 8) >>> 0;
|
||||
sys.poke(out_ptr + idx + 2, s)
|
||||
sys.poke(out_ptr + idx + 3, (s >>> 8) >>> 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
return out;
|
||||
return out_ptr;
|
||||
};
|
||||
|
||||
frame.samplingFrequency = function () {
|
||||
|
||||
@@ -216,6 +216,11 @@ var Frameheader = {
|
||||
var pos = position;
|
||||
|
||||
var buf = source.readFull(4)
|
||||
if (buf.err) {
|
||||
return {
|
||||
err: buf.err
|
||||
}
|
||||
}
|
||||
if (buf.length < 4) {
|
||||
return {
|
||||
h: 0,
|
||||
|
||||
@@ -61,13 +61,16 @@ var Mp3 = {
|
||||
};
|
||||
|
||||
source.readFull = function (length) {
|
||||
if (length < 0) throw Error("Source.pos less than 0: "+source.pos)
|
||||
|
||||
var l = Math.min(source.buf.byteLength - source.pos, length);
|
||||
|
||||
if (l < 0) {
|
||||
serial.println("l < 0: "+l)
|
||||
throw Error("l < 0: "+l)
|
||||
if (length <= 0 || l <= 0 || length === undefined) {
|
||||
return { err: ("Source.pos less than 0: "+source.pos) }
|
||||
}
|
||||
|
||||
if (l <= 0) {
|
||||
serial.println("l <= 0: "+l)
|
||||
throw Error("l <= 0: "+l)
|
||||
}
|
||||
|
||||
// serial.println(`readFull(${length} -> ${l}); pos: ${source.pos}`)
|
||||
@@ -148,25 +151,35 @@ var Mp3 = {
|
||||
err: result.err
|
||||
}
|
||||
}
|
||||
|
||||
decoder.frame = result.f;
|
||||
var pcm_buf = decoder.frame.decode();
|
||||
var [pcm_buf_ptr, pcm_buf_len] = decoder.frame.decode();
|
||||
// decoder.buf = util.concatBuffers(decoder.buf, pcm_buf);
|
||||
return { buf: pcm_buf };
|
||||
|
||||
// serial.println(`End of decoder.readFrame; ptr: ${pcm_buf_ptr} len: ${pcm_buf_len}`)
|
||||
|
||||
return {
|
||||
ptr: pcm_buf_ptr,
|
||||
len: pcm_buf_len,
|
||||
pos: result.position
|
||||
};
|
||||
};
|
||||
|
||||
decoder.decode = function (callback) {
|
||||
var result;
|
||||
|
||||
serial.println("Start decoding")
|
||||
// serial.println("Start decoding")
|
||||
|
||||
while(true) {
|
||||
result = decoder.readFrame();
|
||||
|
||||
if (typeof callback == "function") callback(result)
|
||||
|
||||
if (result.err) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (typeof callback == "function") callback(result.ptr, result.len, result.pos)
|
||||
|
||||
sys.free(result.ptr)
|
||||
|
||||
}
|
||||
// return decoder.buf;
|
||||
};
|
||||
@@ -230,6 +243,9 @@ var Mp3 = {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// serial.println("Reading first frame")
|
||||
|
||||
var result = decoder.readFrame();
|
||||
@@ -240,13 +256,15 @@ var Mp3 = {
|
||||
|
||||
// serial.println("First frame finished reading")
|
||||
|
||||
decoder.headerSize = decoder.source.pos
|
||||
decoder.sampleRate = decoder.frame.samplingFrequency();
|
||||
decoder.frameSize = decoder.frame.header.frameSize()
|
||||
|
||||
serial.println("Sampling rate: "+decoder.sampleRate + " Hz")
|
||||
// serial.println("Sampling rate: "+decoder.sampleRate + " Hz")
|
||||
|
||||
result = decoder.ensureFrameStartsAndLength();
|
||||
|
||||
serial.println("Decode end")
|
||||
// serial.println("Decode end")
|
||||
if (result.err) {
|
||||
throw Error(`Error ensuring Frame starts and length: ${result.err}`)
|
||||
return null;
|
||||
|
||||
@@ -24,7 +24,10 @@ const COL_HL_EXT = {
|
||||
"bas": 215,
|
||||
"bat": 215,
|
||||
"wav": 31,
|
||||
"adpcm": 32,
|
||||
"adpcm": 31,
|
||||
"pcm": 33,
|
||||
"mp3": 34,
|
||||
"mp2": 34,
|
||||
"mov": 213,
|
||||
"ipf1": 190,
|
||||
"ipf2": 191,
|
||||
@@ -35,6 +38,7 @@ const COL_HL_EXT = {
|
||||
const EXEC_FUNS = {
|
||||
"wav": (f) => _G.shell.execute(`playwav ${f} /i`),
|
||||
"adpcm": (f) => _G.shell.execute(`playwav ${f} /i`),
|
||||
"mp3": (f) => _G.shell.execute(`playmp3 ${f} /i`),
|
||||
"mov": (f) => _G.shell.execute(`playmov ${f} /i`),
|
||||
"pcm": (f) => _G.shell.execute(`playpcm ${f} /i`),
|
||||
"ipf1": (f) => _G.shell.execute(`decodeipf ${f} /i`),
|
||||
@@ -46,7 +50,7 @@ let windowMode = 0 // 0 == left, 1 == right
|
||||
let windowFocus = 0 // 0: files window, 1: palette window, 2: popup window
|
||||
|
||||
// window states
|
||||
let path = [["A:"], ["A:"]]
|
||||
let path = [["A:", "home"], ["A:"]]
|
||||
let scroll = [0, 0]
|
||||
let dirFileList = [[], []]
|
||||
let cursor = [0, 0] // absolute position!
|
||||
|
||||
Reference in New Issue
Block a user