Перейти к содержанию
    

mp3 декодер VS1003

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

 

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

 

while(1)
{
MakeSoundBuffer(Buf);
...
}

 

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

 

EXEPTION Handler()

{

for(i=0;i<32;i++) SPISend(Buf);

EOI();

}

 

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

 

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

 

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

 

что делать?

 

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

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

Если Вы не можете обеспечить декодек данными - или выложите, как же Вы пытались, или забудьте про звук.

Чтение из буфера Вы показали, давайте теперь запись.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

В общем такое работает - темп слегка растянут - что и нужно!

Но при интенсивном построении буфера - данный метод работает не очень - много хрипа

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

 

Я извиняюсь, или я сегодня не в себе, или что - но ваши объяснения очень плохо понятны.

- откуда берутся звуковые данные? их откуда-то получают, или вычисляют или что?

- у вас SPI что работает без пирериваний? причем вся пересылка SPI происходит сама в прерывании обработки DREQ? какая частота SPI?

 

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

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...