ESPHome  2025.2.0
audio.cpp
Go to the documentation of this file.
1 #include "audio.h"
2 
3 namespace esphome {
4 namespace audio {
5 
6 // Euclidean's algorithm for finding the greatest common divisor
7 static uint32_t gcd(uint32_t a, uint32_t b) {
8  while (b != 0) {
9  uint32_t t = b;
10  b = a % b;
11  a = t;
12  }
13  return a;
14 }
15 
16 AudioStreamInfo::AudioStreamInfo(uint8_t bits_per_sample, uint8_t channels, uint32_t sample_rate)
17  : bits_per_sample_(bits_per_sample), channels_(channels), sample_rate_(sample_rate) {
18  this->ms_sample_rate_gcd_ = gcd(1000, this->sample_rate_);
19  this->bytes_per_sample_ = (this->bits_per_sample_ + 7) / 8;
20 }
21 
22 uint32_t AudioStreamInfo::frames_to_microseconds(uint32_t frames) const {
23  return (frames * 1000000 + (this->sample_rate_ >> 1)) / this->sample_rate_;
24 }
25 
26 uint32_t AudioStreamInfo::frames_to_milliseconds_with_remainder(uint32_t *total_frames) const {
27  uint32_t unprocessable_frames = *total_frames % (this->sample_rate_ / this->ms_sample_rate_gcd_);
28  uint32_t frames_for_ms_calculation = *total_frames - unprocessable_frames;
29 
30  uint32_t playback_ms = (frames_for_ms_calculation * 1000) / this->sample_rate_;
31  *total_frames = unprocessable_frames;
32  return playback_ms;
33 }
34 
36  return (this->bits_per_sample_ == rhs.get_bits_per_sample()) && (this->channels_ == rhs.get_channels()) &&
37  (this->sample_rate_ == rhs.get_sample_rate());
38 }
39 
40 const char *audio_file_type_to_string(AudioFileType file_type) {
41  switch (file_type) {
42 #ifdef USE_AUDIO_FLAC_SUPPORT
44  return "FLAC";
45 #endif
46 #ifdef USE_AUDIO_MP3_SUPPORT
47  case AudioFileType::MP3:
48  return "MP3";
49 #endif
50  case AudioFileType::WAV:
51  return "WAV";
52  default:
53  return "unknown";
54  }
55 }
56 
57 void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor,
58  size_t samples_to_scale) {
59  // Note the assembly dsps_mulc function has audio glitches if the input and output buffers are the same.
60  for (int i = 0; i < samples_to_scale; i++) {
61  int32_t acc = (int32_t) audio_samples[i] * (int32_t) scale_factor;
62  output_buffer[i] = (int16_t) (acc >> 15);
63  }
64 }
65 
66 } // namespace audio
67 } // namespace esphome
bool operator==(const AudioStreamInfo &rhs) const
Definition: audio.cpp:35
uint8_t get_channels() const
Definition: audio.h:29
uint8_t get_bits_per_sample() const
Definition: audio.h:28
uint32_t frames_to_milliseconds_with_remainder(uint32_t *frames) const
Computes the duration, in milliseconds, the given amount of frames represents.
Definition: audio.cpp:26
uint32_t get_sample_rate() const
Definition: audio.h:30
uint32_t frames_to_microseconds(uint32_t frames) const
Computes the duration, in microseconds, the given amount of frames represents.
Definition: audio.cpp:22
Implementation of SPI Controller mode.
Definition: a01nyub.cpp:7
void scale_audio_samples(const int16_t *audio_samples, int16_t *output_buffer, int16_t scale_factor, size_t samples_to_scale)
Scales Q15 fixed point audio samples.
Definition: audio.cpp:57
const char * audio_file_type_to_string(AudioFileType file_type)
Helper function to convert file type to a const char string.
Definition: audio.cpp:40