Я адаптирую пример для библиотеки Arduino AutoAnalogAudio под названием
SDAudioWavPlayer
который может быть найден в примерах-> AutoAnalogAudio-> SDAudio-> SDAudioWavPlayer
В этом примере используются прерывания для многократного вызова функции
void loadBuffer (). Код для этого ниже
/* Function called from DAC interrupt after dacHandler(). Loads data into the dacBuffer */
void loadBuffer() {
if (myFile) {
if (myFile.available()) {
if (aaAudio.dacBitsPerSample == 8) {
//Load 32 samples into the 8-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer, MAX_BUFFER_SIZE);
}else{
//Load 32 samples (64 bytes) into the 16-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer16, MAX_BUFFER_SIZE * 2);
//Convert the 16-bit samples to 12-bit
for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
}
}
}else{
#if defined (AUDIO_DEBUG)
Serial.println("File close");
#endif
myFile.close();
aaAudio.disableDAC();
}
}
}
Конкретная часть, которая меня интересует, это вторая часть утверждения if
{
//Load 32 samples (64 bytes) into the 16-bit dacBuffer
myFile.read((byte*)aaAudio.dacBuffer16, MAX_BUFFER_SIZE * 2);
//Convert the 16-bit samples to 12-bit
for (int i = 0; i < MAX_BUFFER_SIZE; i++) {
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
}
}
Несмотря на комментарий, MAX_BUFFER_SIZE равен 256, поэтому 512 байтов считываются
aaAudio.dacBuffer16. Эти данные изначально были 16-битными целыми числами со знаком (+/- 32k), а dacBuffer16 является массивом 16-битных целых чисел без знака (0-64K). Отрицательный знак удаляется путем прохождения массива и добавления 2 ^ 15 (0x8000) к каждому элементу. Это приводит к переполнению отрицательных чисел, оставляя положительную часть отрицательного числа. Положительные числа просто увеличились на 2 ^ 15. таким образом, значения изменяются на 0 -64K. Затем результат сдвигается на 4 позиции вправо, так что остаются только старшие 12 битов, что может обрабатывать ЦАП Arduino. Все это происходит в очереди
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> 4;
Все идет нормально.
Теперь я хочу иметь возможность программно уменьшить громкость. Насколько я могу найти, библиотека не предоставляет функцию для этого, поэтому я подумал, что самый простой
нужно было изменить «4» на «N» и увеличить величину смещения до 5,6,7 и т. д.
например
aaAudio.dacBuffer16[i] = (aaAudio.dacBuffer16[i] + 0x8000) >> N;
где N — целое число Я попробовал это, но я получил ужасно искаженный результат, который я не понял.
Играя, пробуя разные вещи, я попробовал следующее, которое работает
uint16_t sample;
int N = 5;
for (int i = 0; i < MAX_BUFFER_SIZE; i++)
{
sample = (aaAudio.dacBuffer16[i] + 0x8000);
sample = sample >> N;
// sample = sample / 40;
aaAudio.dacBuffer16[i] = sample;
}
Вы также можете видеть, что я прокомментировал просто деление на число, которое работает, если я хочу более точный контроль.
Моя проблема в том, что я не вижу разницы между двумя битами кода.
Кто-нибудь может просветить меня?
Задача ещё не решена.
Других решений пока нет …