PCM Audio Player using FFT

Game Introduction

Use TurboWarp for better performance: https://turbowarp.org/941518411?fps=60&hqpen or Forkphorus: https://forkphorus.github.io/?fps=60#941518411 This project uses the fast fourier transform and 257 sine wave assets to play any 16 KHz audio signal without having to import it into the project file as an asset. This also allows us to control the playback rate and go back or forward to play sections of audio as we please, and opens the possibility to generate audio signals with code and play them. Press "i" if you want to import your own audio file, which MUST BE a 16 KHz 16-bit mono signed little-endian PCM hex string. If it isn't, the result will be the wrong speed or sound WAY TOO LOUD. I recommend converting 16 KHz 16-bit mono .wav files to hex with this website, with BOTH CHECKBOXES UNTICKED, and to lower your volume beforehand: https://tomeko.net/online_tools/file_to_hex Credit to @52525rr for inspiration and a tip for improving audio quality. Check out her own FFT audio player v3: https://scratch.mit.edu/projects/683387044/ Music is Never Gonna Give You Up by Rick Astley The Discrete Fourier Transform takes an input discrete signal in the time domain and produces a complex-valued output discrete signal that describes the input signal as a sum of sine waves of various amplitudes and phases. This is the frequency domain representation of the original signal. The Fast Fourier Transform is an optimized algorithm for the discrete fourier transform that runs in O(n log n) time, a significant improvement over the O(n^2) time used by a naive DFT algorithm. With Scratch we can use this frequency domain representation to reconstruct the original signal by using clones to play those sine waves at the provided amplitudes. Phase information is unfortunately lost, so the reconstruction is imperfect—I haven't found a reliable way to precisely control the phase of a sine wave as it plays. Why 16 KHz? One restriction with less sophisticated implementations of the FFT like my own is that the size of the input signal has to be a power of two. Every frame, I take an FFT over an interval of time that covers the next two frames of the input signal. So the effective sample rate is the project frame rate multiplied by half the FFT size. The FFT size determines how many sine waves will be needed to play the sound, and overall how much work will be required each frame. Another consideration is that the sample rate will affect what duration of audio I'll be able to put into the project.json file, which has to fit into the 5 MB size limit. I chose an FFT size of 512, which needs 257 sine waves (because only the first half + 1 of the FFT output is needed for the reconstruction), each whose frequency is a multiple of the reciprocal of the time interval covered by the input signal, starting at 0 times up to 256 times this "base frequency." So, given that this project is designed to run with TurboWarp 60 FPS mode on, then you might expect the sample rate to be 256 * 60 = 15360. But TurboWarp 60 FPS mode doesn't run at exactly 60 FPS—it actually runs a little faster, at 62.5 FPS (If you're curious, this is because the JavaScript setInterval function that Scratch uses will round the frame delay down to the millisecond). Taking advantage of this, we can increase the sample rate to 256 * 62.5 = 16000 Hz. Note: It turns out the behavior of setInterval varies between browsers. The behavior I describe above fits the behavior of Chromium, and the behavior defined in the specification. Safari doesn't seem to do rounding, and Firefox runs the provided function too infrequently. This shouldn't significantly affect how the project sounds. Oct 6, 2024: Changes to audio output in the hopes of improving quality (fixed random pitch strength calculation, sounds no longer restart simultaneously, set low initial pitch value to mitigate popping) Dec 18, 2023: Shared

How To Play

Author

SpinningCube

Category

Game Information

Game Popularity

874 views

Collection Count

64 favorites