Add PUT /api/stream/phone: raw PCM audio push from a phone app
New endpoint accepts chunked, header-less, 16-bit LE stereo PCM @ 48 kHz in the request body and writes it straight to the shared I2S sink for as long as the connection stays open. Chosen deliberately unencoded (no MP3/AAC/Opus decode) to keep this path as simple and low-risk as possible — the companion app controls the encoding on its side. Extracted the I2S TX channel that used to be owned outright by web_radio_stream.cpp into main/esp32_i2s_sink.cpp, shared by both producers with a simple tryAcquire()/release() exclusivity guard — web radio streaming and a phone PCM stream would otherwise fight over the same physical wire. web_radio_stream.cpp now acquires/releases around each streamWhileEnabled() cycle instead of owning the channel itself. net::PhoneStreamSink is a plain function-pointer struct (not a class hierarchy) threaded through NetBootstrap::start() -> SetupWebServer::start() -> HttpRouteContext, so components/net stays free of I2S driver headers; main/phone_stream.cpp supplies the concrete functions (bound to esp32_i2s_sink) and does the int16->ADAU 32-bit-slot conversion, batched per chunk rather than per sample for the same reason as the web radio stutter fix (6974095/7e65394 lineage). Verified by build only — not confirmed live yet (board disconnected this session); the actual phone app that will exercise this endpoint doesn't exist yet either. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0178rASQ6ZETPMUamvpoR2KR
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
* @file esp32_i2s_sink.hpp
|
||||
* @brief Shared ESP32 -> ADAU1701 I2S TX channel (web radio / phone stream).
|
||||
*
|
||||
* DigiRadio firmware — https://github.com/manvalan/DigiRadio
|
||||
*
|
||||
* Copyright 2026 Michele Bigi
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
namespace esp32_i2s_sink {
|
||||
|
||||
/**
|
||||
* Open the shared I2S TX channel (ESP32 as I2S slave, ADAU1701 as master)
|
||||
* on first call; a no-op on later calls. Not thread-safe to call
|
||||
* concurrently with itself — call once during boot.
|
||||
* @return true on success.
|
||||
*/
|
||||
bool open();
|
||||
|
||||
/**
|
||||
* Claim exclusive use of the channel for one producer (web radio stream or
|
||||
* a phone PCM stream). Only one producer may hold it at a time, since both
|
||||
* would otherwise fight over the same physical wire.
|
||||
* @return true if acquired, false if another producer already holds it.
|
||||
*/
|
||||
bool tryAcquire();
|
||||
|
||||
/** Release a previously acquired claim. Safe to call even if not held. */
|
||||
void release();
|
||||
|
||||
/**
|
||||
* Write one frame's worth of already-32-bit-slot-formatted stereo samples
|
||||
* (left, right pairs). Blocks until the DMA accepts the data.
|
||||
* @param samples Interleaved L,R int32 samples (top-aligned 24-bit).
|
||||
* @param sampleCount Number of int32 values in samples (2x frame count).
|
||||
* @return true on success.
|
||||
*/
|
||||
bool writeSamples(const std::int32_t* samples, std::size_t sampleCount);
|
||||
|
||||
} // namespace esp32_i2s_sink
|
||||
Reference in New Issue
Block a user