import { PrismaClient } from "@prisma/client"; import LCD from "raspberrypi-liquid-crystal"; import fs from "node:fs"; import * as WavFileDecoder from "wav-file-decoder"; const timer = (ms) => new Promise((res) => setTimeout(res, ms)); const prisma = new PrismaClient(); const getStanza = async (register) => { const stanzaCount = await prisma.stanza.count({ where: { register } }); const skip = Math.floor(Math.random() * stanzaCount); const randomStanza = await prisma.stanza.findMany({ skip: skip, take: 1, where: { register, }, }); if (!randomStanza || !randomStanza[0].text) { console.log(register, stanzaCount, skip, randomStanza, "no stanza found in db"); // try one more time const anotherStanzaTry = await prisma.stanza.findMany({ skip: skip, take: 1, where: { register, }, }); return anotherStanzaTry[0].text; } return randomStanza[0].text; }; // Play portal wave PCM data and set bands // This file has been downsampled to 1000hz (1,000 samples per second) const fileData = fs.readFileSync("/home/grace/portal/blackportal1000.wav"); const wavFileInfo = WavFileDecoder.getWavFileInfo(fileData); const audioData = WavFileDecoder.decodeWavFile(fileData); const totalSamples = wavFileInfo.chunkInfo.filter((ci) => ci.chunkId === "data")[0].dataLength; let sample = 0; let register = "high"; let count = 0; setInterval(() => { const absSample = Math.abs(audioData.channelData[0][count]); if (count == totalSamples - 1) { count = 0; console.log("total samples reached"); } else { count++; } register = "high"; if (absSample < 0.01) { register = "mid"; } if (absSample < 0.001) { register = "low"; } sample = absSample; }, 1); // Setup lcd screen const lcd = new LCD(1, 0x27, 16, 2); lcd.beginSync(); lcd.clearSync(); const TICK = 250; const WAIT = 10; // Play bottom line const tag = " Black Portal 4856 E Davison, Detroit "; let tagCharacterLocation = 0; setInterval(() => { lcd.printLineSync(1, " "); setTimeout(() => { lcd.printLineSync(1, tag.substring(tagCharacterLocation, tag.length)); }, WAIT); tagCharacterLocation++; if (tagCharacterLocation > tag.length) { tagCharacterLocation = 0; } }, TICK); let characterLocation = 0; let stanzaText = ""; let endBuffer = ""; let totalTicks = 0; // Play top line while (true) { if (characterLocation == totalTicks) { characterLocation = 0; stanzaText = await getStanza(register); endBuffer = stanzaText.length > 16 ? "" : Array(16 - stanzaText.length).join(" "); totalTicks = stanzaText.length + endBuffer.length; } if (!stanzaText) { console.log("no stanza text in stanza scroller"); } lcd.printLineSync(0, " "); setTimeout(() => { lcd.printLineSync(0, `${characterLocation < 16 ? Array(16 - characterLocation).join(" ") : ""}${stanzaText + endBuffer}`.substring(characterLocation, totalTicks)); }, WAIT); await timer(TICK); characterLocation++; }