-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathAudio.cpp
115 lines (96 loc) · 2.88 KB
/
Audio.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include "Audio.h"
#include "Debug.h"
#include "PrintString.h"
#include "user_interface.h"
#include <AudioGeneratorFLAC.h>
#include <umm_malloc/umm_heap_select.h>
// #include <AudioGeneratorMP3.h>
#include <AudioOutputBuffer.h>
#include <memory>
String get_base_name(FsFile& file)
{
PrintString base_name;
file.printName(&base_name);
return base_name.getString();
}
std::unique_ptr<AudioManager> AudioManager::instance;
AudioManager& AudioManager::the()
{
HeapSelectIram iram;
if (!AudioManager::instance)
AudioManager::instance = std::make_unique<AudioManager>();
return *AudioManager::instance.get();
}
AudioManager::AudioManager()
: audio_source(card)
, audio_output(0, AudioOutputI2S::EXTERNAL_I2S, 8,
AudioOutputI2S::APLL_DISABLE)
{
timer.attach_ms(1, audio_timer_interrupt);
}
void metadata_callback(void*, char const* key, bool is_unicode, char const* value)
{
// TODO: Provide the metadata back to the AudioManager so UI can read it out.
// PrintString output;
// output.printf_P(PSTR("Audio: Metadata: %s = %s\n"), key, value);
// debug_print(output.getString());
}
void error_callback(void*, int code, char const* string)
{
// PrintString output;
// output.printf_P(PSTR("Audio: Status code %d: %s\n"), code, string);
// debug_print(output.getString());
}
void AudioManager::play(String& file_name)
{
if (audio_player)
audio_player->stop();
audio_source.close();
if (file_name.endsWith(F(".flac"))) {
audio_player = std::make_unique<AudioGeneratorFLAC>();
// } else if (file_name.endsWith(F(".mp3"))) {
// audio_player = std::make_unique<AudioGeneratorMP3>();
}
if (!audio_source.open(file_name.c_str())) {
return;
}
audio_player->RegisterMetadataCB(&metadata_callback, nullptr);
audio_player->RegisterStatusCB(&error_callback, nullptr);
audio_player->begin(&audio_source, &audio_output);
debug_print(F("Audio: Starting playback"));
}
float AudioManager::current_position() const
{
auto sample_rate = audio_output.sample_rate();
auto sample_count = audio_output.sample_count();
return static_cast<float>(static_cast<double>(sample_count) / sample_rate);
}
enum class Frequency : bool {
Mhz160,
Mhz80,
};
extern "C" void preloop_update_frequency() { }
void set_frequency(Frequency frequency)
{
uint8_t target_freq = frequency == Frequency::Mhz160 ? SYS_CPU_160MHZ : SYS_CPU_80MHZ;
uint8_t current_freq = system_get_cpu_freq();
if (current_freq != target_freq) {
system_update_cpu_freq(target_freq);
char t[64];
snprintf_P(t, sizeof(t), PSTR("CPU: Clocking to %d MHz (from %d MHz)"), target_freq, current_freq);
debug_print(t);
}
}
void AudioManager::loop()
{
if (audio_player && audio_player->isRunning()) {
set_frequency(Frequency::Mhz160);
if (!audio_player->loop()) {
audio_player->stop();
debug_print(F("Audio: Track ended."));
}
} else {
set_frequency(Frequency::Mhz80);
}
}
void audio_timer_interrupt() { AudioManager::the().loop(); }