Playing audio with speakers (2024)

CC: Tweaked's speaker peripheral provides a powerful way to play any audio you like with the speaker.playAudiomethod. However, for people unfamiliar with digital audio, it's not the most intuitive thing to use. This guide providesan introduction to digital audio, demonstrates how to play music with CC: Tweaked's speakers, and then briefly discussesthe more complex topic of audio processing.

A short introduction to digital audio

When sound is recorded it is captured as an analogue signal, effectively the electrical version of a soundwave. However, this signal is continuous, and so can't be used directly by a computer. Instead, we measure (or sample)the amplitude of the wave many times a second and then quantise that amplitude, rounding it to the nearestrepresentable value.

This representation of sound - a long, uniformally sampled list of amplitudes is referred to as Pulse-codeModulation (PCM). PCM can be thought of as the "standard" audio format, as it's incredibly easy to work with. Forinstance, to mix two pieces of audio together, you can just add samples from the two tracks together and take the average.

CC: Tweaked's speakers also work with PCM audio. It plays back 48,000 samples a second, where each sample is an integerbetween -128 and 127. This is more commonly referred to as 48kHz and an 8-bit resolution.

Let's now look at a quick example. We're going to generate a Sine Wave at 220Hz, which sounds like a low monotonoushum. First we wrap our speaker peripheral, and then we fill a table (also referred to as a buffer) with 128×1024samples - this is the maximum number of samples a speaker can accept in one go.

In order to fill this buffer, we need to do a little maths. We want to play 220 sine waves each second, where each sinewave completes a full oscillation in 2π "units". This means one seconds worth of audio is 2×π×220 "units" long. We thenneed to split this into 48k samples, basically meaning for each sample we move 2×π×220/48k "along" the sine curve.

local speaker = peripheral.find("speaker")local buffer = {}local t, dt = 0, 2 * math.pi * 220 / 48000for i = 1, 128 * 1024 do buffer[i] = math.floor(math.sin(t) * 127) t = (t + dt) % (math.pi * 2)endspeaker.playAudio(buffer)

Streaming audio

You might notice that the above snippet only generates a short bit of audio - 2.7s seconds to be precise. While we couldtry increasing the number of loop iterations, we'll get an error when we try to play it through the speaker: the soundbuffer is too large for it to handle.

Our 2.7 seconds of audio is stored in a table with over 130 thousand elements. If we wanted to play a full minute ofsine waves (and why wouldn't you?), you'd need a table with almost 3 million. Suddenly you find these numbers addingup very quickly, and these tables take up more and more memory.

Instead of building our entire song (well, sine wave) in one go, we can produce it in small batches, each of which getpassed off to speaker.playAudio when the time is right. This allows us to build a stream of audio, where we readchunks of audio one at a time (either from a file or a tone generator like above), do some optional processing to eachone, and then play them.

Let's adapt our example from above to do that instead.

local speaker = peripheral.find("speaker")local t, dt = 0, 2 * math.pi * 220 / 48000while true do local buffer = {} for i = 1, 16 * 1024 * 8 do buffer[i] = math.floor(math.sin(t) * 127) t = (t + dt) % (math.pi * 2) end while not speaker.playAudio(buffer) do os.pullEvent("speaker_audio_empty") endend

It looks pretty similar to before, aside from we've wrapped the generation and playing code in a while loop, and added arather odd loop with speaker.playAudio and os.pullEvent.

Let's talk about this loop, why do we need to keep calling speaker.playAudio? Remember that what we're trying to dohere is avoid keeping too much audio in memory at once. However, if we're generating audio quicker than the speakers canplay it, we're not helping at all - all this audio is still hanging around waiting to be played!

In order to avoid this, the speaker rejects any new chunks of audio if its backlog is too large. When this happens,speaker.playAudio returns false. Once enough audio has played, and the backlog has been reduced, aspeaker_audio_empty event is queued, and we can try to play our chunk once more.

Storing audio

PCM is a fantastic way of representing audio when we want to manipulate it, but it's not very efficient when we want tostore it to disk. Compare the size of a WAV file (which uses PCM) to an equivalent MP3, it's often 5 times the size.Instead, we store audio in special formats (or codecs) and then convert them to PCM when we need to do processing onthem.

Modern audio codecs use some incredibly impressive techniques to compress the audio as much as possible while preservingsound quality. However, due to CC: Tweaked's limited processing power, it's not really possible to use these from yourcomputer. Instead, we need something much simpler.

DFPWM (Dynamic Filter Pulse Width Modulation) is the de facto standard audio format of the ComputerCraft (andOpenComputers) world. Originally popularised by the addon mod Computronics, CC:T now has built-in support for it withthe cc.audio.dfpwm module. This allows you to read DFPWM files from disk, decode them to PCM, and then play themusing the speaker.

Let's dive in with an example, and we'll explain things afterwards:

local dfpwm = require("cc.audio.dfpwm")local speaker = peripheral.find("speaker")local decoder = dfpwm.make_decoder()for chunk in io.lines("data/example.dfpwm", 16 * 1024) do local buffer = decoder(chunk) while not speaker.playAudio(buffer) do os.pullEvent("speaker_audio_empty") endend

Once again, we see the speaker.playAudio/speaker_audio_empty loop. However, the rest of the program is a littledifferent.

First, we require the dfpwm module and call cc.audio.dfpwm.make_decoder to construct a new decoder. This decoderaccepts blocks of DFPWM data and converts it to a list of 8-bit amplitudes, which we can then play with our speaker.

As mentioned above, speaker.playAudio accepts at most 128×1024 samples in one go. DFPWM uses a single bit for eachsample, which means we want to process our audio in chunks of 16×1024 bytes (16KiB). In order to do this, we useio.lines, which provides a nice way to loop over chunks of a file. You can of course just use fs.open andfs.ReadHandle.read if you prefer.

Processing audio

As mentioned near the beginning of this guide, PCM audio is pretty easy to work with as it's just a list of amplitudes.You can mix together samples from different streams by adding their amplitudes, change the rate of playback by removingsamples, etc...

Let's put together a small demonstration here. We're going to add a small delay effect to the song above, so that youhear a faint echo a second and a half later.

In order to do this, we'll follow a format similar to the previous example, decoding the audio and then playing it.However, we'll also add some new logic between those two steps, which loops over every sample in our chunk of audio, andadds the sample from 1.5 seconds ago to it.

For this, we'll need to keep track of the last 72k samples - exactly 1.5 seconds worth of audio. We can do this using aRing Buffer, which helps makes things a little more efficient.

local dfpwm = require("cc.audio.dfpwm")local speaker = peripheral.find("speaker")-- Speakers play at 48kHz, so 1.5 seconds is 72k samples. We first fill our buffer-- with 0s, as there's nothing to echo at the start of the track!local samples_i, samples_n = 1, 48000 * 1.5local samples = {}for i = 1, samples_n do samples[i] = 0 endlocal decoder = dfpwm.make_decoder()for chunk in io.lines("data/example.dfpwm", 16 * 1024) do local buffer = decoder(chunk) for i = 1, #buffer do local original_value = buffer[i] -- Replace this sample with its current amplitude plus the amplitude from 1.5 seconds ago. -- We scale both to ensure the resulting value is still between -128 and 127. buffer[i] = original_value * 0.6 + samples[samples_i] * 0.4 -- Now store the current sample, and move the "head" of our ring buffer forward one place. samples[samples_i] = original_value samples_i = samples_i + 1 if samples_i > samples_n then samples_i = 1 end end while not speaker.playAudio(buffer) do os.pullEvent("speaker_audio_empty") end -- The audio processing above can be quite slow and preparing the first batch of audio -- may timeout the computer. We sleep to avoid this. -- There's definitely better ways of handling this - this is just an example! sleep(0.05)end
🛈 Confused?

Don't worry if you don't understand this example. It's quite advanced, and does use some ideas that this guide doesn'tcover. That said, don't be afraid to ask the community for help.

It's worth noting that the examples of audio processing we've mentioned here are about manipulating the amplitude ofthe wave. If you wanted to modify the frequency (for instance, shifting the pitch), things get rather more complex.For this, you'd need to use the Fast Fourier transform to convert the stream of amplitudes to frequencies,process those, and then convert them back to amplitudes.

This is, I'm afraid, left as an exercise to the reader.

See also

  • speaker.playAudio Play PCM audio using a speaker.
  • cc.audio.dfpwm Provides utilities for encoding and decoding DFPWM files.
Playing audio with speakers (2024)

FAQs

How do I play audio on multiple speakers? ›

If your speakers lack built-in multi-connect, you can use an audio splitter:
  1. Obtain a dual RCA or 3.5mm audio splitter.
  2. Connect the source device's audio output to the splitter's input port.
  3. Connect the speakers to the splitter's output ports.
  4. Turn on the speakers and source device.
Mar 6, 2024

How do I get sound to play through external speakers? ›

Select Start > Settings > System > Sound. In the Output section, select the device you want to use for playback as your output device.

How do I get my computer to play through my speakers? ›

1. Check your speaker output
  1. Select the Speakers icon on the taskbar.
  2. Next, select the arrow to the right of the speaker volume slider to open a list of audio devices connected to your computer. ...
  3. Check that your audio is playing to the audio device you prefer, such as a speaker or headphones.

How do I play music through all speakers? ›

With music or other media playing:
  1. Open the Google Home app .
  2. Tap Favorites .
  3. On the mini-player, tap Cast .
  4. Tap each device that you want to add. All selected devices have a check . Any compatible devices that are linked to your account or on your Wi-Fi network are displayed.

Can you play off two speakers at once? ›

Certain portable Bluetooth speakers have a setting aptly named Party Mode, where they both play music simultaneously. This makes it possible to take your music on the go, playing your favorite songs all across your campsite, boat, or backyard setup.

Why won't my sound play through speakers? ›

Make sure your speakers are turned on and the volume is high enough. Unmute all audio components on your PC, sound devices, and apps. Re-connect all audio cables in case they have become loose. Disconnect your headphones to check if your speakers turn on by default.

How do I change audio Output to speakers? ›

Quick Steps
  1. Click the up-arrow in your taskbar to open the system tray.
  2. Click the speaker icon.
  3. Click the arrow next to the current audio output.
  4. Select a new audio output.

Why aren't my wired speakers working? ›

Wired speakers attach to either the headphone jack or a USB port. Check the connection to the computer and the power source (probably the wall). Repair your Bluetooth device if that's how you typically get sound, and confirm that the battery isn't dead. Check the volume and mute settings.

How do I turn on dual audio? ›

Turn on Multipoint
  1. On your Android device, tap Settings. Connected devices.
  2. Next to your device, tap Settings .
  3. Tap Multipoint. Use Multipoint.
  4. Connect your headphones with the 2 desired audio source devices. To make sure your headphones are connected, go to Bluetooth settings on the audio source device.

What is the app that plays music on two speakers? ›

AmpMe is the #1 portable sound system that connects you to friends, family, strangers (and even aliens)!

How do I enable external speakers on my computer? ›

How do I get my computer to play through my speakers? On Windows, go to Start > Settings > System > Sound, then select your speakers as the default output device. On a Mac, go to System Settings > Sound, select Output on the right, then select your connected speaker.

Why is my PC not detecting external speakers? ›

Fix 2: Set Speaker as Default Device

If your laptop has not selected the external speakers as a playback default device, you will encounter the issue of external speakers not working. For this, you can change the settings to set speakers as the default device.

What is the best way to connect speakers to a computer? ›

Wired speakers or headphones - can be connected to a desktop or laptop using a 3.5mm audio connector or a USB cable. Wireless speakers or headphones - can be connected to a Bluetooth-capable computer using Bluetooth.

How do I play the same song on multiple speakers? ›

How to Connect Multiple Bluetooth Speakers to One Device
  1. Make sure that the Bluetooth functionality of both devices is enabled.
  2. Refer to your device's integrated Bluetooth search for devices available for connection.
  3. Choose the multiple Bluetooth speakers you want to link to your phone.
Dec 9, 2022

How to set up dual audio on iPhone? ›

Within the Control Center, locate and tap on the Music option. This will display the currently connected device playing the audio. Look for the Share Audio option and tap on it. Your iPhone will automatically detect compatible headphones and prompt you to share the music with them.

Top Articles
Sardinia World Chess Festival: Live
Skyway Proboards
Urist Mcenforcer
Craigslist Vans
Usborne Links
Ds Cuts Saugus
Senior Tax Analyst Vs Master Tax Advisor
Devotion Showtimes Near Mjr Universal Grand Cinema 16
Braums Pay Per Hour
Robert Malone é o inventor da vacina mRNA e está certo sobre vacinação de crianças #boato
Gma Deals And Steals Today 2022
Midlife Crisis F95Zone
Google Flights Missoula
Itziar Atienza Bikini
Hocus Pocus Showtimes Near Amstar Cinema 16 - Macon
Missed Connections Dayton Ohio
Craigslist West Valley
The Pretty Kitty Tanglewood
Rural King Credit Card Minimum Credit Score
Curver wasmanden kopen? | Lage prijs
Zack Fairhurst Snapchat
Webcentral Cuny
Kaitlyn Katsaros Forum
Puss In Boots: The Last Wish Showtimes Near Cinépolis Vista
Walmart Near South Lake Tahoe Ca
A Christmas Horse - Alison Senxation
Fuse Box Diagram Honda Accord (2013-2017)
Xxn Abbreviation List 2023
How rich were the McCallisters in 'Home Alone'? Family's income unveiled
The Monitor Recent Obituaries: All Of The Monitor's Recent Obituaries
Rush County Busted Newspaper
Used 2 Seater Go Karts
MethStreams Live | BoxingStreams
Rust Belt Revival Auctions
Skroch Funeral Home
42 Manufacturing jobs in Grayling
Emerge Ortho Kronos
Ursula Creed Datasheet
Wisconsin Women's Volleyball Team Leaked Pictures
Pp503063
Legit Ticket Sites - Seatgeek vs Stubhub [Fees, Customer Service, Security]
2020 Can-Am DS 90 X Vs 2020 Honda TRX90X: By the Numbers
Urban Blight Crossword Clue
Wasmo Link Telegram
Unblocked Games Gun Games
Fool's Paradise Showtimes Near Roxy Stadium 14
Craigslist Houses For Rent Little River Sc
Jane Powell, MGM musical star of 'Seven Brides for Seven Brothers,' 'Royal Wedding,' dead at 92
Concentrix + Webhelp devient Concentrix
Superecchll
Costco Gas Price Fort Lauderdale
Asisn Massage Near Me
Latest Posts
Article information

Author: Corie Satterfield

Last Updated:

Views: 6349

Rating: 4.1 / 5 (42 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Corie Satterfield

Birthday: 1992-08-19

Address: 850 Benjamin Bridge, Dickinsonchester, CO 68572-0542

Phone: +26813599986666

Job: Sales Manager

Hobby: Table tennis, Soapmaking, Flower arranging, amateur radio, Rock climbing, scrapbook, Horseback riding

Introduction: My name is Corie Satterfield, I am a fancy, perfect, spotless, quaint, fantastic, funny, lucky person who loves writing and wants to share my knowledge and understanding with you.