Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32 mp3 playback
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > ARM
Страницы: 1, 2, 3
winner
Цитата(zksystem @ Aug 16 2010, 11:08) *
Вы название темы читали?


Про playbaak ? Да прочитал - playbaak-ом Вы и занимаетесь.
zksystem
Цитата(winner @ Aug 16 2010, 13:02) *
Про playbaak ? Да прочитал - playbaak-ом Вы и занимаетесь.

Тут речь о STM32 велась, а вы со своим ARM9 тут и линуксом ни к селу ни городу. Вот я о чем.
kan35
Цитата(Ivan Kuznetzov @ Aug 11 2010, 09:22) *
В общем попытался тут заменить на сявый polyphase.c - а там вставки для винды, не проканает.

Ну неужели ни у кого нет asmpoly.s под STM32 для IARa ?

У меня все проканало, правда немного покумекать пришлось. Занимался с год назад... Если кому то еще актуально:
http://narod.ru/disk/438694001/hellyx_stm32_iar552.rar.html
Ivan Kuznetzov
Цитата(kan35 @ Nov 28 2010, 00:35) *
У меня все проканало, правда немного покумекать пришлось. Занимался с год назад... Если кому то еще актуально:
http://narod.ru/disk/438694001/hellyx_stm32_iar552.rar.html


Блиин! конечно актуально! Спасибо!

Что делает прерывание TIM1_CC_Handler? Как необходимо настроить этот таймер?
kan35
Цитата(Ivan Kuznetzov @ Nov 30 2010, 09:34) *
Блиин! конечно актуально! Спасибо!

Что делает прерывание TIM1_CC_Handler? Как необходимо настроить этот таймер?

По TIM1_CC_Handler я выводил звук через ШИМ (44кГц, 10бит) - 2 буфера по-очереди выводились в ШИМ.
В общем, делайте вывод звука сами, так как мой вариант был просто для тестирования декодера.
Ivan Kuznetzov
kan35, какой максимальный битрейт Вам удалось воспроизвести с помощью этого кодека?
kan35
Цитата(Ivan Kuznetzov @ Dec 2 2010, 09:15) *
kan35, какой максимальный битрейт Вам удалось воспроизвести с помощью этого кодека?

В общем я только проверил на том кусочке, который в виде таблицы находится в файле mp3.h (там чуть более секунды). На сколько я помню (смотрел JTAG-ом) у него был 128кбит (не точно), и точно: частота 44100, стерео. На 72МГц процесс отъедал около 40% CPU.
Спрашивали как инициализировал таймер, код. То что относится к RTOS, LCD я думаю выбросить не составить труда:
CODE
void TIM1_CC_IRQHandler(void)
{
TIM1_ClearITPendingBit(TIM1_IT_CC1);
extern void TIM1_CC_Handler(void);
TIM1_CC_Handler();
}



void Task_Extra(void)
{
// Timer1 Init
// Enable Timer1 clock and release reset
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);
RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);

// Set timer period 0.5 sec
TIM1_TimeBaseInitTypeDef TIM1_TimeBaseInitStruct;
TIM1_TimeBaseInitStruct.TIM1_Prescaler = 0;
TIM1_TimeBaseInitStruct.TIM1_CounterMode = TIM1_CounterMode_Up;
TIM1_TimeBaseInitStruct.TIM1_Period = 1632;//
TIM1_TimeBaseInitStruct.TIM1_ClockDivision = TIM1_CKD_DIV1;
TIM1_TimeBaseInitStruct.TIM1_RepetitionCounter = 0;
TIM1_TimeBaseInit(&TIM1_TimeBaseInitStruct);

// Clear update interrupt bit
//TIM1_ClearITPendingBit(TIM1_FLAG_Update);
// Enable update interrupt
//TIM1_ITConfig(TIM1_FLAG_Update,ENABLE);

//PWM SETUP
TIM1_OCInitTypeDef ocr_str;
TIM1_OCStructInit( &ocr_str );
ocr_str.TIM1_OCMode = TIM1_OCMode_PWM1;
ocr_str.TIM1_OutputState = TIM1_OutputState_Enable;
ocr_str.TIM1_Pulse = 800;
ocr_str.TIM1_OCPolarity = TIM1_OCPolarity_High;
TIM1_OC1Init(&ocr_str);
TIM1_OC1PreloadConfig(TIM1_OCPreload_Enable);

// TIM1 Main Output Enable
TIM1_CtrlPWMOutputs(ENABLE);

// Compare interrupt enable
TIM1_ITConfig(TIM1_IT_CC1, ENABLE);

/*GPIOA Configuration: TIM1 channel 1 as alternate function push-pull */
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);




NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM1_CC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 12;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
// Enable timer counting


TIM1_Cmd(ENABLE);

HD44780_PowerUpInit();
HD44780_ReturnToHome();

OS_TIMER TIMERTEST;
OS_CreateTimer(&TIMERTEST, NULL, 100000);
unsigned int j = 0;
while (1)
{
OS_RetriggerTimer(&TIMERTEST);
void decoder( void );
decoder( );
OS_StopTimer(&TIMERTEST);
char buf[50];
unsigned int data = 100000 - OS_GetTimerValue(&TIMERTEST);
//data /= 1.28;
sprintf(buf, "%d %d ", data, j++);//
HD44780_ReturnToHome();
for (int i = 0; buf[i]!=0 && i<20; i++)
{
OS_Delay(1);
HD44780WrData(buf[i]);
}
}
}

И по старую периферийную библиотеку все сделано, я думаю, тоже не составить труда перевести под новую.
Ivan Kuznetzov
Кто-нибудь пробовал 12и битный DAC на STM32? Сильно звук паршивый?
=F8=
Цитата(Ivan Kuznetzov @ Jul 14 2011, 22:20) *
Кто-нибудь пробовал 12и битный DAC на STM32? Сильно звук паршивый?

Для телефонии вполне даже ничего. Сильно зависит от аналогового питания. Чтоб шумело поменьше пришлось запититывать от отдельного линейного стабилизатора.
Ivan Kuznetzov
Запустил пример, компилятор IAR. Все время выходит из функции MP3Decode в самом начале:
Код
    if (!mp3DecInfo)
        return ERR_MP3_NULL_POINTER;


Проблема была в маленьком HEAP - указал побольше (0x5000) и стало играть.
Теперь надо как-то декодированный буфер через DMA гнать в I2S. А то на 192кбит/с немножко затыкается. Интерфейс с картой SPI. На SDIO будет получше конечно.
sonycman
Цитата(Ivan Kuznetzov @ Jul 17 2011, 16:15) *
А то на 192кбит/с немножко затыкается. Интерфейс с картой SPI. На SDIO будет получше конечно.

Дык там даже при 320 kbps поток с карточки не превышает 40 кб\сек, а это смешная скорость даже для 1 битного интерфейса.
Думаю, затыки в самом декодере или где то ещё.
Ivan Kuznetzov
С декодером разобрался! Юзаю Helix через два встроенных DAC STM32F103VET6. Вопрс теперь по кодированию в MP3. Могу писать WAV c АЦП-шника, хочется его после записи закодировать в mp3 и wav удалить. Есть для этого подходящие либы?
Ivan Kuznetzov
Сделал вывод стерео через ШИМ. ШИМ 70кГц. Качество примерно как у аудиокассеты, но вполне слушабельно...
kan35
Цитата(Ivan Kuznetzov @ Dec 13 2011, 16:05) *
Сделал вывод стерео через ШИМ. ШИМ 70кГц. Качество примерно как у аудиокассеты, но вполне слушабельно...

не вполне ясно откуда берется 70кГц???
все же DAC существенно лучше: во первых битность больше на тех же 44кГц, во вторых - проще фильтровать.
На моем образце большинство людей разницу с фабричными плеерами не замечают, так что я бы сказал качество выше аудиокассетного существенно.
И в обоих случаях требуется выдавать звук через DMA.
Ivan Kuznetzov
Цитата(kan35 @ Dec 14 2011, 00:36) *
не вполне ясно откуда берется 70кГц???
все же DAC существенно лучше: во первых битность больше на тех же 44кГц, во вторых - проще фильтровать.
На моем образце большинство людей разницу с фабричными плеерами не замечают, так что я бы сказал качество выше аудиокассетного существенно.
И в обоих случаях требуется выдавать звук через DMA.

С DAC у меня тоже работает (STM32F103VET6), согласен, качество существенно лучше.
ШИМ приделывал c целью возможности использования на проце, где ДАКа нету...
AHTOXA
Позвольте поинтересоваться, удалось ли добиться нормального воспроизведения 320 kbps mp3 на STM32F1xx? Вроде были сообщения, что не тянут они?
kan35
Цитата(AHTOXA @ Dec 14 2011, 23:36) *
Позвольте поинтересоваться, удалось ли добиться нормального воспроизведения 320 kbps mp3 на STM32F1xx? Вроде были сообщения, что не тянут они?

на скомпилированном в иаре 320 кбит грузит проц на 40-45%
Ivan Kuznetzov
Цитата(AHTOXA @ Dec 15 2011, 01:36) *
Позвольте поинтересоваться, удалось ли добиться нормального воспроизведения 320 kbps mp3 на STM32F1xx? Вроде были сообщения, что не тянут они?

подтверждаю, прекрасно тянет! работаю на helix mp3dec. сорцы полностью сявые.
sonycman
Цитата(kan35 @ Dec 15 2011, 19:59) *
на скомпилированном в иаре 320 кбит грузит проц на 40-45%

Выше на этой же странице Ваш пост про 40% загрузку процессора уже на 128 килобитах.
А теперь тоже самое на 320?

Другой декодер?
kan35
Цитата(sonycman @ Dec 16 2011, 11:20) *
Выше на этой же странице Ваш пост про 40% загрузку процессора уже на 128 килобитах.
А теперь тоже самое на 320?

Другой декодер?

Посмотрите https://datatype.helixcommunity.org/Mp3dec табличку зависимости загрузки от битрейта.

Скажу подробно: плеер работает во freertos, и я снимаю статистику загрузки штатными средствами и она показывает 57% напроцесс плеера, при этом все отсчеты (коих однако 88200 в секунду) проходят "софтверную" нормализацию, если это "вычесть", а так же "вычесть" чтение из файла (оно производится в этом же потоке), потому я примерно прикинул - 40-45% (72МГц).
AHTOXA
Ну что ж, очень радостно слышатьsm.gif
Надо будет попробовать...
skripach
Приветствую!
Добавил к проекту Helix MP3 декодер, всё здорово работает, ресурсов хватает, но есть один неприятный момент когда останавливаю декодирование в призвольном месте и запускаю новый трек то вначеле воспроизведения слышны "остатки" предыдущего трека. Свои буферы я сбрасываю, - это где-то в самом декодере.
Как с этим бороться?
Jhonny.
Подскажите пожалуйста, как скачать код с helixcommunity.org?
kan35
skripach,
Я думаю самый надежный способ удалять созданный плеер каждый раз при прерывании звука, а перед запуском нового звука создавать снова.

Цитата(Jhonny. @ Apr 13 2013, 18:13) *
Подскажите пожалуйста, как скачать код с helixcommunity.org?

https://player.helixcommunity.org/2005/downloads/
Архивчики плеера в правой колонке. После скачивания найдете в папках и mp3 плеер и много чего еще.
Sergey_Aleksandrovi4
Здравствуйте. Пытаюсь в своём проекте реализовать воспроизведение mp3 на базе helix-декодера. Звук вывел уже на второй день работы, третью неделю не могу решить проблемы с производительностью. На 72 МГц всё процессорное время уходит на проигрывание 44,1 кГц стерео. Привожу время полного декодирования фрейма для разного битрейта на 44.1 кГц. Непосредственно функция MP3Decode() выполняется на 2..3 мс меньше. Для времени воспроизведения фрейма в 26,12 мс выходит, что кодек "тянет" только аудио с битрейтом 128 кбит/с. Файлы с более высоким битрейт вплоть до 320 играются с искажениями (на слух почти не уловимыми).
Контроллер STM32F105. AHB на 72 МГц (проверено), APB на 36 МГц. Тело mp3 хранится во встроенной Flash, декодирование и вывод через пинг-понг буфер, вывод через DMA в ЦАП. ОС не использую, суперлуп. Прерывания только от DMA ЦАП ,SysTIck и UART (отладочный порт).

Буфера для декодирования фрейма статические, динамическую память не использую, стек на время тестов раздул до 2 кБайт. Компилятор IAR ARM 6.50.
Что делал:
1. Задрал уровень оптимизации компилятора до максимального по скорости. Выиграл не более 10%. Отпадает.
2. Грешил на медленный доступ ко Flash, сократил число циклов ожидания доступа до 1 (такой оверклокинг). Производительность возросла ~5%. Мимо.
3. Исследовал функции из ассемблерного "asmmisc.s", время выполнения MULSHIFT32() и FASTABS() относительно сильно, но не так критически влияет на скорость работы. Мимо. Полифазный фильтр в "asmpoly_thumb2.s " взял как есть без переделок (правил только синтаксис с gcc на IAR), т.е. как у всех.
4. Явно указал на необходимость встраивания inline-функций через #pragma inline
5. mp3-файл менял на другой (думал, может кривой фрагмент попался). Не помогло.

Анализируя опыт разработчиков с этого и с других сторонних ресурсов, понимаю, что производительность должна быть в 2 раза выше. Буду благодарен за любую помощь и советы. Не хочется из-за собственной ошибки переходить на 20х семейство.

upd прикрепил два asm-файла (копирайт от RealNetworks удалил для экономии места), грешу всё-таки на них. Может кто сравнить со своими в IAR-проекте?
asmmisc.s
CODE


REQUIRE8
PRESERVE8

SECTION .text:CODE:NOROOT(2)
PUBLIC MULSHIFT32
THUMB
MULSHIFT32
smull r2, r0, r1, r0
//mov pc, lr // KJ changed to BX for Cortex
BX lr



SECTION .text:CODE:NOROOT(2)
PUBLIC FASTABS
THUMB
FASTABS
mov r1, r0
mov r0, #0x0
eor r0, r1, r1, asr # 31
sub r0, r0, r1, asr # 31
bx lr

END


asmpoly_thumb2.s
CODE


#define PCM r0
#define VB1 r1
#define COEF r2
; must push PCM ptr to stack during inner looop
#define VLO r0
; temp variable
#define VHI r3

#define SUM1LL r4
#define SUM1LH r5
#define SUM2LL r6
#define SUM2LH r7
#define SUM1RL r8
#define SUM1RH r9
#define SUM2RL r10
#define SUM2RH r11

#define CF1 r12
#define CF2 r14

; used for clipping - after discarding CF1
#define SIGN r12
; used for clipping - after discarding CF2
#define MAXPOS r14
; overlay loop counter with CF1, SIGN
#define I r12



#define RNDVAL (1 << ((32 - 12) + (6 - 1)))

/*; C64TOS - clip 64-bit accumulator to short (no rounding)
; xl, xh = value (lo 32, hi 32)
; input assumed to have 6 fraction bits
; sign = temp variable to use for sign
; maxPos = 0x00007fff (takes 2 instr. to generate - calculating
; once and using repeatedly saves if you do several CTOS in a row) */
C64TOS MACRO _xl, _xh, _sign, _maxPos
mov _xl, _xl, lsr #(20+6)
orr _xl, _xl, _xh, lsl #(12-6)
mov _sign, _xl, ASR #31
cmp _sign, _xl, ASR #15
it ne
eorne _xl, _sign, _maxPos
ENDM ; C64TOS

/* ; MC0S - process 2 taps, 1 sample per channel (sample 0) */
/* ; x = vb1 offset */
MC0S MACRO val_x
ldr CF1, [COEF], #4
ldr CF2, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
ldr VHI, [VB1, #(4*(23 - val_x))]

smlal SUM1LL, SUM1LH, VLO, CF1
ldr VLO, [VB1, #(4*(32 + val_x))]
rsb CF2, CF2, #0
smlal SUM1LL, SUM1LH, VHI, CF2
ldr VHI, [VB1, #(4*(32 + 23 - val_x))]

smlal SUM1RL, SUM1RH, VLO, CF1
smlal SUM1RL, SUM1RH, VHI, CF2
ENDM ;MC0S

/* ; MC1S - process 2 taps, 1 sample per channel (sample 16)
; x = vb1 offset */
MC1S MACRO val_x
ldr CF1, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
ldr VHI, [VB1, #(4*(32 + val_x))]
smlal SUM1LL, SUM1LH, VLO, CF1
smlal SUM1RL, SUM1RH, VHI, CF1
ENDM ;MC1S

/* ; MC2S - process 2 taps, 2 samples per channel
; x = vb1 offset */
MC2S MACRO val_x
/* ; load data as far as possible in advance of using it */
ldr CF1, [COEF], #4
ldr CF2, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
ldr VHI, [VB1, #(4*(23 - val_x))]

smlal SUM1LL, SUM1LH, VLO, CF1
smlal SUM2LL, SUM2LH, VLO, CF2
rsb CF2, CF2, #0
smlal SUM2LL, SUM2LH, VHI, CF1
smlal SUM1LL, SUM1LH, VHI, CF2

ldr VHI, [VB1, #(4*(32 + 23 - val_x))]
ldr VLO, [VB1, #(4*(32 + val_x))]

smlal SUM1RL, SUM1RH, VHI, CF2
smlal SUM2RL, SUM2RH, VHI, CF1
rsb CF2, CF2, #0
smlal SUM1RL, SUM1RH, VLO, CF1
smlal SUM2RL, SUM2RH, VLO, CF2
ENDM ;MC2S








/* ; void PolyphaseStereo(short *pcm, int *vbuf, const int *coefBase) */
SECTION .text:CODE:NOROOT(2)
PUBLIC xmp3_PolyphaseStereo
THUMB
xmp3_PolyphaseStereo:

stmfd sp!, {r4-r11, r14}

/* ; clear out stack space for 2 local variables (4 bytes each) */
sub sp, sp, #8
str PCM , [sp, #4] /*; sp[1] = pcm pointer */

/* ; special case, output sample 0 */
mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM1LH, #0
mov SUM1RH, #0

MC0S 0
MC0S 1
MC0S 2
MC0S 3
MC0S 4
MC0S 5
MC0S 6
MC0S 7

ldr PCM, [sp, #4] /* ; load pcm pointer */
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS
C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS

strh SUM1LL, [PCM, #(2*0)]
strh SUM1RL, [PCM, #(2*1)]

/* ; special case, output sample 16 */
add COEF, COEF, #(4*(256-16)) /* ; coef = coefBase + 256 (was coefBase + 16 after MC0S block) */
add VB1, VB1, #(4*1024) /* ; vb1 = vbuf + 64*16 */

mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM1LH, #0
mov SUM1RH, #0

MC1S 0
MC1S 1
MC1S 2
MC1S 3
MC1S 4
MC1S 5
MC1S 6
MC1S 7

ldr PCM, [sp, #4] /* load pcm pointer */
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS
C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS

strh SUM1LL, [PCM, #(2*(2*16+0))]
strh SUM1RL, [PCM, #(2*(2*16+1))]

/*; main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17 */
sub COEF, COEF, #(4*(264-16)) /* ; coef = coefBase + 16 (was coefBase + 264 after MC1S block) */
sub VB1, VB1, #(4*(1024-64)) /* ; vb1 = vbuf + 64 (was vbuf + 64*16 after MC1S block) */
mov I, #15 /* ; loop counter, count down */
add PCM, PCM, #(2*2) /* ; pcm+=2 */

LoopPS:
str I, [sp, #0] /* ; sp[0] = i (loop counter) */
str PCM, [sp, #4] /* ; sp[1] = pcm (pointer to pcm buffer) */

mov SUM1LL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM1RL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM2LL, #RNDVAL /* ; load rndVal (low 32) */
mov SUM2RL, #RNDVAL /* ; load rndVal (low 32) */

mov SUM1LH, #0
mov SUM1RH, #0
mov SUM2LH, #0
mov SUM2RH, #0

MC2S 0
MC2S 1
MC2S 2
MC2S 3
MC2S 4
MC2S 5
MC2S 6
MC2S 7

add VB1, VB1, #(4*64) /*; vb1 += 64*/

ldr PCM, [sp, #4] /*; load pcm pointer*/
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS
C64TOS SUM1RL, SUM1RH, SIGN, MAXPOS
C64TOS SUM2LL, SUM2LH, SIGN, MAXPOS
C64TOS SUM2RL, SUM2RH, SIGN, MAXPOS

ldr I, [sp, #0] /*; load loop counter*/
add CF2, PCM, I, lsl #3 /*; CF2 = PCM + 4*i (short offset)*/
strh SUM2LL, [CF2], #2 /*; *(pcm + 2*2*i + 0)*/
strh SUM2RL, [CF2], #2 /*; *(pcm + 2*2*i + 1)*/

strh SUM1LL, [PCM], #2 /*; *(pcm + 0)*/
strh SUM1RL, [PCM], #2 /*; *(pcm + 1)*/

subs I, I, #1
bne LoopPS

/* ; restore stack pointer*/
add sp, sp, #8

ldmfd sp!, {r4-r11, pc}
/* ENDFUNC*/















/*;; MONO PROCESSING*/

/*; MC0M - process 2 taps, 1 sample (sample 0)*/
/*; x = vb1 offset*/
MC0M MACRO val_x
ldr CF1, [COEF], #4
ldr CF2, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
ldr VHI, [VB1, #(4*(23 - val_x))]

rsb CF2, CF2, #0
smlal SUM1LL, SUM1LH, VLO, CF1
smlal SUM1LL, SUM1LH, VHI, CF2
ENDM ;MC0M


/*; MC1M - process 2 taps, 1 sample (sample 16)*/
/*; x = vb1 offset*/
MC1M MACRO val_x
ldr CF1, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
smlal SUM1LL, SUM1LH, VLO, CF1
ENDM ;MC1M


/* ; MC2M - process 2 taps, 2 samples*/
/* ; x = vb1 offset*/
MC2M MACRO val_x
/* ; load data as far as possible in advance of using it*/
ldr CF1, [COEF], #4
ldr CF2, [COEF], #4
ldr VLO, [VB1, #(4*(val_x))]
ldr VHI, [VB1, #(4*(23 - val_x))]

smlal SUM1LL, SUM1LH, VLO, CF1
smlal SUM2LL, SUM2LH, VLO, CF2
rsb CF2, CF2, #0
smlal SUM1LL, SUM1LH, VHI, CF2
smlal SUM2LL, SUM2LH, VHI, CF1
ENDM ;MC2M



/*; void PolyphaseMono(short *pcm, int *vbuf, const int *coefBase)*/
SECTION .text:CODE:NOROOT(2)
PUBLIC xmp3_PolyphaseMono
THUMB
xmp3_PolyphaseMono:

stmfd sp!, {r4-r11, r14}

/*; clear out stack space for 4 local variables (4 bytes each)*/
sub sp, sp, #8
str PCM, [sp, #4] /*; sp[1] = pcm pointer*/

/* ; special case, output sample 0*/
mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/
mov SUM1LH, #0

MC0M 0
MC0M 1
MC0M 2
MC0M 3
MC0M 4
MC0M 5
MC0M 6
MC0M 7

ldr PCM, [sp, #4] /*; load pcm pointer*/
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS
strh SUM1LL, [PCM, #(2*0)]

/* ; special case, output sample 16*/
add COEF, COEF, #(4*(256-16)) /* ; coef = coefBase + 256 (was coefBase + 16 after MC0M block)*/
add VB1, VB1, #(4*1024) /* ; vb1 = vbuf + 64*16*/

mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/
mov SUM1LH, #0

MC1M 0
MC1M 1
MC1M 2
MC1M 3
MC1M 4
MC1M 5
MC1M 6
MC1M 7

ldr PCM, [sp, #4] /* ; load pcm pointer*/
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS

strh SUM1LL, [PCM, #(2*16)]

/* ; main convolution loop: sum1L = samples 1, 2, 3, ... 15 sum2L = samples 31, 30, ... 17*/
sub COEF, COEF, #(4*(264-16)) /* ; coef = coefBase + 16 (was coefBase + 264 after MC1M block)*/
sub VB1, VB1, #(4*(1024-64)) /* ; vb1 = vbuf + 64 (was vbuf + 64*16 after MC1M block)*/
mov I, #15 /* ; loop counter, count down*/
add PCM, PCM, #(2) /* ; pcm++*/

LoopPM:
str I, [sp, #0] /* ; sp[0] = i (loop counter)*/
str PCM, [sp, #4] /* ; sp[1] = pcm (pointer to pcm buffer)*/

mov SUM1LL, #RNDVAL /* ; load rndVal (low 32)*/
mov SUM2LL, #RNDVAL /* ; load rndVal (low 32)*/
mov SUM1LH, #0
mov SUM2LH, #0

MC2M 0
MC2M 1
MC2M 2
MC2M 3
MC2M 4
MC2M 5
MC2M 6
MC2M 7

add VB1, VB1, #(4*64) /*; vb1 += 64*/

ldr PCM, [sp, #4] /*; load pcm pointer*/
mov MAXPOS, #0x7f00
orr MAXPOS, MAXPOS, #0xff

C64TOS SUM1LL, SUM1LH, SIGN, MAXPOS
C64TOS SUM2LL, SUM2LH, SIGN, MAXPOS

ldr I, [sp, #0] /*; load loop counter*/
add CF2, PCM, I, lsl #2 /*; CF2 = PCM + 2*i (short offset)*/
strh SUM2LL, [CF2], #2 ; /**(pcm + 2*i + 0)*/
strh SUM1LL, [PCM], #2 ; /**(pcm + 0) ; pcm++*/

subs I, I, #1
bne LoopPM
/* ; restore stack pointer*/
add sp, sp, #8
ldmfd sp!, {r4-r11, pc}


END
kan35
Я делал эти функции в Сишном виде. Где то 40-50% ресурсов отъедал под FreeRTOS. Сделайте следующее: возьмите фрагмент и декодируйте его на скорость, без выдачи в ЦАП. Я думаю, у вас проблемы где то в процедурах выдачи звука.
Sergey_Aleksandrovi4
Цитата(kan35 @ Sep 23 2013, 22:56) *
Сделайте следующее: возьмите фрагмент и декодируйте его на скорость, без выдачи в ЦАП.

Сделал. На декодирование 177 фреймов 320 kbits стерео при medium оптимизации затрачено 4.712 с, т.е. в среднем 26.6 мс на фрейм. Сижу, ищу наиболее ресурсоотжирающий кусок алгоритма. Не в выводе дело.


Нажмите для просмотра прикрепленного файла
Функция MP3Decode() из "mp3dec.c". Один фрейм состоит из двух гранул.
Участок A 1,25 мс. Относительно быстро
CODE
for (ch = 0; ch < mp3DecInfo->nChans; ch++)
{
// unpack scale factors and compute size of scale factor block
prevBitOffset = bitOffset;
offset = UnpackScaleFactors(mp3DecInfo, mainPtr, &bitOffset, mainBits, gr, ch);

sfBlockBits = 8*offset - prevBitOffset + bitOffset;
huffBlockBits = mp3DecInfo->part23Length[gr][ch] - sfBlockBits;
mainPtr += offset;
mainBits -= sfBlockBits;

if (offset < 0 || mainBits < huffBlockBits)
{
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_SCALEFACT;
}
// decode Huffman code words
prevBitOffset = bitOffset;
offset = DecodeHuffman(mp3DecInfo, mainPtr, &bitOffset, huffBlockBits, gr, ch);
if (offset < 0)
{
MP3ClearBadFrame(mp3DecInfo, outbuf);
return ERR_MP3_INVALID_HUFFCODES;
}
mainPtr += offset;
mainBits -= (8*offset - prevBitOffset + bitOffset);
}


Участок B 1,25 мс. Относительно быстро
Код
        if (Dequantize(mp3DecInfo, gr) < 0)
        {
            MP3ClearBadFrame(mp3DecInfo, outbuf);
            return ERR_MP3_INVALID_DEQUANTIZE;            
        }


Участок C 3,5 мс. Антиалайзинговый фильтр и пр. Относительно долго
Код
        for (ch = 0; ch < mp3DecInfo->nChans; ch++)
        {
            if (IMDCT(mp3DecInfo, gr, ch) < 0)
            {
                MP3ClearBadFrame(mp3DecInfo, outbuf);
                return ERR_MP3_INVALID_IMDCT;            
            }
        }


Участок D 6,25 мс. Самый долгий участок алгоритма. Как раз он использует ассемблерный модуль asmpoly_thumb2.s
Код
        if (Subband(mp3DecInfo, outbuf + gr*mp3DecInfo->nGranSamps*mp3DecInfo->nChans) < 0)
        {
            MP3ClearBadFrame(mp3DecInfo, outbuf);
            return ERR_MP3_INVALID_SUBBAND;            
        }



Получается, что либо число гранул должно быть 1 вместо двух, либо время выполнения каждого из приведённых выше участков декодера должно быть в раза меньше.
kan35
Уберите из проекта асемблерный файл,так как вероятно в нем проблема(Откуда он? в пакете руддшч с оффиц. сайта я не наблюдал). И подключите другой с Сишными с теми же функциями:
CODE

static inline int MULSHIFT32(int x, int y)
{
return (((long long)x)*((long long)y))>>32;
}

static inline int FASTABS(int x)
{
int sign;

sign = x >> (sizeof(int) * 8 - 1);
x ^= sign;
x -= sign;

return x;
}

static inline int CLZ(int x)
{
int numZeros;

if (!x)
return (sizeof(int) * 8);

numZeros = 0;
while (!(x & 0x80000000)) {
numZeros++;
x <<= 1;
}

return numZeros;
}

static inline Word64 MADD64(Word64 sum, int x, int y)
{
return (sum + ((Word64)x * y));
}

static inline Word64 SAR64(Word64 sum, int x)
{
return (sum >> x);
}


И еще, точно ли у вас работает контролер на 72МГц?
Sergey_Aleksandrovi4
kan35, спасибо большое Вам, что оказываете мне поддержку. Очень признателен.

1. Частота AHB точно 72 МГц. Сигнал выведен на MCO, смотрю его осциллографом.
2. Ассемблерные файлы брал из проекта CircleOS http://www.stm32circle.com/projects/project.php?id=82. Правил синтаксис под IAR. Этот проект частенько на страницах форума фигурирует. Однако пишут, что производительность на 320 кбит/с у него не очень
Цитата
The implementation makes it possible to listen to most common variants of MP3. 320kbit files can have small problems due to speed of the microcontroller.

3. Убрал ассемблерные файлы, подключил "polyphase.c", использовал Ваши встроенные функции (указал на принудительное встраивание через #pragma inline=forced). Время декодирования фрейма (выполнения ф-ции MP3Decode() ) возросло на 30% с 26 до 33 мс. Я в замешательстве.

По helix'у на stm32 очень противоречивые сведения. У кого-то работает, как например у Вас или вот здесь http://we.easyelectronics.ru/STM32/program...kaem-zvuki.html (фрейм 320 кбит/с декодируется чуть-ли не за 13 мс, проект под CooCox IDE).
Здесь http://electronix.ru/forum/lofiversion/index.php/t74280.html aaarrr пишет: "Хорошо, другой пример. Cortex-M3 @ 72MHz, близкая к 100% загрузка при 320кБит/с."

Может быть у меня mp3 файл кривой? Могу я попросить Вас проиграть его на плеере с Вашей реализацией и сообщить результат?
alexandermas
Оптимизируйте декодер. У меня на 120 мгц мп3 декодируется при загрузке камня 10-15%, а flac при 7-10%, при условии что файл забирается с ftp. При 204мгц уже тянет flac 384кгц, и 70% загрузке камня. Загрузку считаю по времяни нахождения в idle ф-ции ртоса. так что пилите гирю, она золотая...
Sergey_Aleksandrovi4
Цитата(kan35 @ Sep 26 2013, 19:19) *
И еще, точно ли у вас работает контролер на 72МГц?

Таки да, ядро работало на 36 МГц. Контролировал частоту на выводе MCO, на который подавалась не тактовая с AHB, а системная SysCLK. Поэтому задействованный делитель х2 я и не заметил. Две недели коту под хвост(
zheka
у кого -нибудь есть проект под KEIL?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.