Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: mp3 декодер VS1003
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > Все остальные микроконтроллеры
denebopetukius
к контроллеру подключен 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 байта это ведь мало?

в даташите упоминается о потоковом режиме. что это такое и поможет ли он в данной ситуации?
Dog Pawlowa
Цитата(denebopetukius @ Apr 6 2009, 07:57) *
подскажите как следует организовать программу по заполнению буфера/чтению из него?

Если Вы не можете обеспечить декодек данными - или выложите, как же Вы пытались, или забудьте про звук.
Чтение из буфера Вы показали, давайте теперь запись.
denebopetukius
согласно тем же докам - мы можем пропихать без опроса 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 байта пока не прийдут новые данные.

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

Поясните как можно сделать лучше...
RodionGork
Цитата(denebopetukius @ Apr 7 2009, 03:05) *
согласно тем же докам - мы можем пропихать без опроса DREQ не более 32 байта. после этого DREQ=0, до тех пор пока часть не отиграет. Затем када


Я извиняюсь, или я сегодня не в себе, или что - но ваши объяснения очень плохо понятны.
- откуда берутся звуковые данные? их откуда-то получают, или вычисляют или что?
- у вас SPI что работает без пирериваний? причем вся пересылка SPI происходит сама в прерывании обработки DREQ? какая частота SPI?

Я тупой наверное очень, но 32 байта на скорости 22050 это больше одной миллисекунды играния... За это время по-моему можно успеть все на свете... Хотя я не в курсе что у вас там с видео происходит, и насколько оно мешает...

Насчет DREQ... Правильно... почти... Только DREQ опускается не до тех пор, пока "отыграет", а до тех пор, когда освободится место для еще 32 байт... Зря вы на него самого прерывание вешаете... Он довольно произвольно может опускаться и подниматься... Лучше записывать данные когда удобно программе (где-нить по таймеру вставить и т.п., разумеется с условием что срабатывать это чаще чем раз в 1мс должно) - проверяя DREQ... Впрочем и так, вероятно, можно... Насчет "кусков и половинок" я не понял... Комментарии не сказать чтоб особо ясные, извините. Чаю попью, может понятливее стану... ;-)
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.