denebopetukius 0 6 апреля, 2009 Опубликовано 6 апреля, 2009 · Жалоба к контроллеру подключен 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 байта это ведь мало? в даташите упоминается о потоковом режиме. что это такое и поможет ли он в данной ситуации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DogPawlowa 0 6 апреля, 2009 Опубликовано 6 апреля, 2009 · Жалоба подскажите как следует организовать программу по заполнению буфера/чтению из него? Если Вы не можете обеспечить декодек данными - или выложите, как же Вы пытались, или забудьте про звук. Чтение из буфера Вы показали, давайте теперь запись. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
denebopetukius 0 6 апреля, 2009 Опубликовано 6 апреля, 2009 · Жалоба согласно тем же докам - мы можем пропихать без опроса 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 0 15 апреля, 2009 Опубликовано 15 апреля, 2009 · Жалоба согласно тем же докам - мы можем пропихать без опроса DREQ не более 32 байта. после этого DREQ=0, до тех пор пока часть не отиграет. Затем када Я извиняюсь, или я сегодня не в себе, или что - но ваши объяснения очень плохо понятны. - откуда берутся звуковые данные? их откуда-то получают, или вычисляют или что? - у вас SPI что работает без пирериваний? причем вся пересылка SPI происходит сама в прерывании обработки DREQ? какая частота SPI? Я тупой наверное очень, но 32 байта на скорости 22050 это больше одной миллисекунды играния... За это время по-моему можно успеть все на свете... Хотя я не в курсе что у вас там с видео происходит, и насколько оно мешает... Насчет DREQ... Правильно... почти... Только DREQ опускается не до тех пор, пока "отыграет", а до тех пор, когда освободится место для еще 32 байт... Зря вы на него самого прерывание вешаете... Он довольно произвольно может опускаться и подниматься... Лучше записывать данные когда удобно программе (где-нить по таймеру вставить и т.п., разумеется с условием что срабатывать это чаще чем раз в 1мс должно) - проверяя DREQ... Впрочем и так, вероятно, можно... Насчет "кусков и половинок" я не понял... Комментарии не сказать чтоб особо ясные, извините. Чаю попью, может понятливее стану... ;-) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться