реклама на сайте
подробности

 
 
> mp3 декодер VS1003, непрерывный поток данных
denebopetukius
сообщение Apr 6 2009, 04:57
Сообщение #1


Местный
***

Группа: Новичок
Сообщений: 221
Регистрация: 13-11-08
Пользователь №: 41 584



к контроллеру подключен VS1003 на SPI.

есть основной цикл программы, подготавливающий буфер аудио-данных:

Код
while(1)
{
MakeSoundBuffer(Buf);
...
}


есть обработчик прерывания VS1003 (по высокому уровню ножки DREQ):

EXEPTION Handler()
{
for(i=0;i<32;i++) SPISend(Buf[i]);
EOI();
}

тоесть Buf - буфер из 32 байт, по прерыванию засылаем 32 байта в mp3 декодер (по даташиту именно столько можно слать без опроса DREQ)

проблема в том что функция MakeSoundBuffer или остальная часть в программе в главном цикле - очень медленна - буфер не успевает построиться полностью, когда mp3-кодер его уже требует.

в итоге вместо непрерываного звука слышен хрип.

что делать?

подскажите как следует организовать программу по заполнению буфера/чтению из него?

32 байта это ведь мало?

в даташите упоминается о потоковом режиме. что это такое и поможет ли он в данной ситуации?


--------------------
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов
denebopetukius
сообщение Apr 6 2009, 23:05
Сообщение #2


Местный
***

Группа: Новичок
Сообщений: 221
Регистрация: 13-11-08
Пользователь №: 41 584



согласно тем же докам - мы можем пропихать без опроса DREQ не более 32 байта. после этого DREQ=0, до тех пор пока часть не отиграет. Затем када снова DREQ=1 - кладем опять 32 байта... итд.

Даже если допустить дергание DREQ во время пересылки данных по SPI, ничего левого не будет - так как мы в высокоприоритетном обработчике прерывания с запрещенными вложенностями. Прерывание по высокому уровню.

8 бит моно 22050Гц. 32 байта буфер , итого 22050/32=690 Гц - воспринимаем прерывание DREQ как прерывание таймера 690 Гц.

Код
#define SND_BUFSIZE 512

Loop:
    dos_update_input(); //Апдейтим кнопки
    audio_update(); //Обновляем буфер когда сэмулировался фрейм
    update_video(); //Отрисовка на экран
goto Loop;

extern volatile u32 Ready; //Признак готовности свежих данных
extern volatile u32 Part; //Смещение которое устанавливает половинки буфера
extern volatile u8 SOUND_BUFFER[SND_BUFSIZE<<1]; //Аудиобуфер из 2-х половинок

void audio_update(void) //Обновляем данные
{
   Ready=0; //Данные ещё не готовы
   for(i=0;i<SND_BUFSIZE;i++) SOUND_BUFFER[Part+i]=f(i); //Строим волну в одной половинке буфера
   Ready=1; //Данные готовы
}

/Макрос посылки 32 байт в VS1003
#define Send32 \
{ \
register u32 i0=(u32)SOUND_BUFFER+(Part^SND_BUFSIZE)+(Kusok<<5); \
register u32 i1=i0+32; \
for(;i0<i1;i0++) SPI(*(u8*)i0); \
}

EX_INTERRUPT_HANDLER(FlagA_ISR) //Обрабоччег прерывания по DREQ
{
*pFIO_FLAG_C=0x0080; //Подтверждаем прерывание
Send32 //Посылаем 32 байта
Kusok++; //Инкрементируем на 32 байта в половинке буфера
if(Kusok==(SND_BUFSIZE>>5)) if(Ready) //Если последний кусок и данные новые поступали
{
Ready=0; //Готовность сбрасываем
Kusok=0; //Сначала в половинку
Part^=SND_BUFSIZE; //Меняем половинки
}
else Kusok=(SND_BUFSIZE>>5)-1; //В противном случае данные не поступали но не можем же мы заткнуться просто так - поэтому играем последнее!!!!
}


В общем данные читаются быстрее, чем они подготавливаются!!!
Потому что выборка 22050 буфер 512 байт, это 22050/512=43 Гц - данные обновляются с меньшей частотой.
Отключаю отрисовку экрана - звук нормальный.

Поэтому сделано воспроизведение последнего куска 32 байта пока не прийдут новые данные.

В общем такое работает - темп слегка растянут - что и нужно!
Но при интенсивном построении буфера - данный метод работает не очень - много хрипа

Поясните как можно сделать лучше...


--------------------
Go to the top of the page
 
+Quote Post



Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 22nd August 2025 - 08:00
Рейтинг@Mail.ru


Страница сгенерированна за 0.0137 секунд с 7
ELECTRONIX ©2004-2016