FastLED 3.9.15
Loading...
Searching...
No Matches
audio_input.h
Go to the documentation of this file.
1#pragma once
2
3
4#pragma once
5
6#include "fl/stdint.h"
7#include "fl/int.h"
8#include "fl/vector.h"
9#include "fl/variant.h"
10#include "fl/shared_ptr.h"
11#include "fl/audio.h"
12#include "fl/compiler_control.h"
13#include "platforms/audio.h"
14
15#ifndef FASTLED_HAS_AUDIO_INPUT
16#error "platforms/audio.h must define FASTLED_HAS_AUDIO_INPUT"
17#endif
18
19
20#define I2S_AUDIO_BUFFER_LEN 512
21#define AUDIO_DEFAULT_SAMPLE_RATE 44100ul
22#define AUDIO_DEFAULT_BIT_RESOLUTION 16
23#define AUDIO_DMA_BUFFER_COUNT 8
24
25namespace fl {
26
27// Note: Right now these are esp specific, but they are designed to migrate to a common api.
28
29enum AudioChannel {
30 Left = 0,
31 Right = 1,
32 Both = 2, // Two microphones can be used to capture both channels with one AudioSource.
33};
34
35
36enum I2SCommFormat {
37 Philips = 0X01, // I2S communication I2S Philips standard, data launch at second BCK
38 MSB = 0X02, // I2S communication MSB alignment standard, data launch at first BCK
39 PCMShort = 0x04, // PCM Short standard, also known as DSP mode. The period of synchronization signal (WS) is 1 bck cycle.
40 PCMLong = 0x0C, // PCM Long standard. The period of synchronization signal (WS) is channel_bit*bck cycles.
41 Max = 0x0F, // standard max
42};
43
44struct AudioConfigI2S {
45 int mPinWs;
46 int mPinSd;
47 int mPinClk;
48 int mI2sNum;
49 AudioChannel mAudioChannel;
50 u16 mSampleRate;
51 u8 mBitResolution;
52 I2SCommFormat mCommFormat;
53 bool mInvert;
54 AudioConfigI2S(
55 int pin_ws,
56 int pin_sd,
57 int pin_clk,
58 int i2s_num,
59 AudioChannel mic_channel,
60 u16 sample_rate,
61 u8 bit_resolution,
62 I2SCommFormat comm_format = Philips,
63 bool invert = false
64 )
65 : mPinWs(pin_ws), mPinSd(pin_sd), mPinClk(pin_clk),
66 mI2sNum(i2s_num), mAudioChannel(mic_channel),
67 mSampleRate(sample_rate), mBitResolution(bit_resolution), mCommFormat(comm_format), mInvert(invert) {}
68};
69
70struct AudioConfigPdm {
71 int mPinDin;
72 int mPinClk;
73 int mI2sNum;
74 u16 mSampleRate;
75 bool mInvert = false;
76
77 AudioConfigPdm(int pin_din, int pin_clk, int i2s_num, u16 sample_rate = AUDIO_DEFAULT_SAMPLE_RATE, bool invert = false)
78 : mPinDin(pin_din), mPinClk(pin_clk), mI2sNum(i2s_num), mSampleRate(sample_rate), mInvert(invert) {}
79};
80
81
82class AudioConfig : public fl::Variant<AudioConfigI2S, AudioConfigPdm> {
83public:
84 // The most common microphone on Amazon as of 2025-September.
85 static AudioConfig CreateInmp441(int pin_ws, int pin_sd, int pin_clk, AudioChannel channel, u16 sample_rate = 44100ul, int i2s_num = 0) {
86 AudioConfigI2S config(pin_ws, pin_sd, pin_clk, i2s_num, channel, sample_rate, 16);
87 return AudioConfig(config);
88 }
89 AudioConfig(const AudioConfigI2S& config) : fl::Variant<AudioConfigI2S, AudioConfigPdm>(config) {}
90 AudioConfig(const AudioConfigPdm& config) : fl::Variant<AudioConfigI2S, AudioConfigPdm>(config) {}
91};
92
93class IAudioInput {
94public:
95 // This is the single factory function for creating the audio source. If the creation was successful, then
96 // the return value will be non-null. If the creation was not successful, then the return value will be null
97 // and the error_message will be set to a non-empty string.
98 // Keep in mind that the AudioConfig is a variant type. Many esp types do not support all the types in the variant.
99 // For example, the AudioConfigPdm is not supported on the ESP32-C3 and in this case it will return a null pointer
100 // and the error_message will be set to a non-empty string.
101 // Implimentation notes:
102 // It's very important that the implimentation uses a esp task / interrupt to fill in the buffer. The reason is that
103 // there will be looooong delays during FastLED show() on some esp platforms, for example idf 4.4. If we do
104 // poll only, then audio buffers can be dropped. However if using a task then the audio buffers will be
105 // set internally via an interrupt / queue and then they can just be popped off the queue.
106 static fl::shared_ptr<IAudioInput> create(const AudioConfig& config, fl::string* error_message = nullptr);
107
108
109 virtual ~IAudioInput() = default;
110 // Starts the audio source.
111 virtual void start() = 0;
112 // Stops the audio source, call this before light sleep.
113 virtual void stop() = 0;
114
115 virtual bool error(fl::string* msg = nullptr) = 0; // if an error occured then query it here.
116 // Read audio data and return as AudioSample with calculated timestamp.
117 // Returns invalid AudioSample on error or when no data is available.
118 virtual AudioSample read() = 0;
119
120 // Read all available audio data and return as AudioSample. All AudioSamples
121 // returned by this will be valid.
122 size_t readAll(fl::vector_inlined<AudioSample, 16> *out) {
123 size_t count = 0;
124 while (true) {
125 AudioSample sample = read();
126 if (sample.isValid()) {
127 out->push_back(sample);
128 count++;
129 } else {
130 break;
131 }
132 }
133 return count;
134 }
135
136};
137
138
139// Free function for audio input creation - can be overridden by platform-specific implementations
140fl::shared_ptr<IAudioInput> platform_create_audio_input(const AudioConfig& config, fl::string* error_message = nullptr) FL_LINK_WEAK;
141
142} // namespace fl
fl::AudioConfig config
Definition AudioInput.h:27
void push_back(const T &value)
Definition vector.h:1061
#define FL_LINK_WEAK
unsigned char u8
Definition int.h:17
FL_LINK_WEAK fl::shared_ptr< IAudioInput > platform_create_audio_input(const AudioConfig &config, fl::string *error_message)
int read()
Definition io.cpp:148
InlinedVector< T, INLINED_SIZE > vector_inlined
Definition vector.h:1220
IMPORTANT!
Definition crgb.h:20