Jump to content

    

__inline__

Участник
  • Content Count

    743
  • Joined

  • Last visited

Everything posted by __inline__


  1. Подскажите кодек для сжатия музыки, можно с потерями. Требования к кодеку: 1) Должен быть опенсорсным и написан на C/C++ (кроссплатформенность и следование ANSI C приветствуются) 2) Декодирование занимает не более 80 миллиоонов операций в секунду 3) Поддерживается фиксированная длина одного фрейма (пакета) сжатия 4) Регулируемая длина в байтах одного фрейма 5) Можно на floating point 6) Требования к декодированию с любого места - отсутствуют, мне нужно последовательно декодировать Всякие MP3 не прокатывают ввиду их относительной жручести и кривого размера одного фрейма. ADPCM не подходит из-за низкого коэффициента сжатия 4:1
  2. Переписал mathops.h на интрисинки C6745 и включил быструю аппроксимацию в config.h - скорость декодирования выросла : теперь фрейм разжимается 0,56 мс. Но можно было и не оптимизировать, а включить FIXED_POINT в config.h и пересобрать. Вариант FIXED POINT на 5% быстрее оптимизированного FLOATING POINT + FAST APPROX. Пробовал CELT 10 и 11 версии. 11-я версия пошла фтопку, так как кодек отказался работать на моём формате. А вот 10-я версия работает, хотя пакеты несовместимы с 9-й. Оставил 10-ю версию. Всё что выше 10й - уже похерено Опусом.
  3. Проделал ряд экспериментов с кодеками на ПК и на доске с C6745. 1) Кодек MP2. На 32 кГц 48 кбит/c 1 канал - качество заметно хуже, чем у MP3 на тех же параметрах. Конкретно - сильно режет высокие частоты, звук как будто приглушён. 2) Кодек Opus. Ребята из Xiph.org явно перегнули палку с ним. Нет никакого кодека Opus на самом деле. Есть два разных кодека: для речи- SILK, для музыки -CELT. То, что называется Opus'ом - это некая предварительная прослойка, которая анализирует фрейм и параметры: если фрейм речевой - отсылает на SILK, если музыкальный - то отсылка на CELT. При этом, конечно, сжирается некий вычислительный процент на такой анализ. А у меня чисто музыка. Поэтому было решено перейти к кодеку под пунктом 3) ниже: 3) Кодек CELT. Конкретно собрал версию 0.9.0. Хватает за глаза! Читаем описание и видим: поддержка семплрейта от 32 (!!!) до 96 кГц - то что мне нужно!!! А в Opus 32 кГц запретили. Далее - размер фрейма : от 64 до 512 семплов. Нет привязки к тупым миллисекундам как в Opus ! Итоговый битрейт считается как : BitRate = FrequencySample/FrameSize*CompressedFrame*8 BitRate -битрейт бит/c FrequencySample - частота дискретизации Гц FrameSize - размер фрейма (исходного) в семплах (1 семпл = 2 байта) CompressedFrame - размер фрейма (сжатого) в байтах По формуле выше определяется размер сжатого фрейма, при заданном целевом битрейте (выходном). Результаты ошеломляющие - без всяких спец-оптимизаций и интринсиков удалось декодировать на лету фреймы всего 0,96 мс при таких параметрах: 1 канал, 48 кбит/c, 32 кГц, размер разжатого фрейма 512 семплов. Выходит в Opus жестко ограничили возможности CELT'а и притормозили его! А вот если переписать mathops на интринсики C6745, думаю можно ещё больше ускорить работу кодека. И по качеству CELT сравним с MP3 и превосходит MP2 на одинаковых параметрах. Задача выполнена. Кодек CELT с исходниками: http://www.celt-codec.org/downloads/ Моя байда с проверкой кодека на ПК:
  4. TI в C6745 сделала SDIO аж 8-битным (что для e-MMC очень прекрасно), но эти лапки к сожалению также сидят на EMIFA, а там дисплей у меня. Делать мультиплексор и разделять во времени работу с LCD и картой - не вариант. И перекидывать ноги на разные функции как сделано в STM32 нет возможности. Но я приобрёл больше с С6745 , чем потерял на STM32. )) Правда есть возможность сделать ногодрыг на PRU или софтово, но поезд ушел - железка в релизе: SD карта там через SPI. Я тут копаю кодек CELT - это бомба - качество лучше, чем у MP3 на таких параметрах 32 кГц 48 кбит/c 1 канал. Для музыки в видео-играх идеально, даже в наушниках хорошо звучит. И сжатие лучше в 2-4 раза, чем у 4-битного ADPCM при том же качестве звука (чисто субъективная оценка). А это меньше данных грузить с SD-карты - быстрее загрузка. Декодирование на лету - по фреймам 512 семплов: как раз 16 мс(это период следования прерываний McASP ) выходит на 48 кбит/c - чуть больше 60 FPS с VSYNC (сам декодер разжимает фрейм всего 0,96 мс) Мои эксперименты с кодеком CELT:
  5. STM32H743 MDMA

    Использую H743 на отладочной плате Nucleo. Работал с DMA, DMA2D - всё чудесно и превосходно: с AXI RAM отправляю буфер в LCD-дисплей по шине FMC 8-бит (дисплей со своим контроллером и видеопамятью). Но не хватает опции перестановки байтов, потому что LCD требует передавать старший, затем младший байт. Пока использую REV16 per pixel. Хочу избавиться от REV16, применив MDMA в котором можно включить перестановку байтов (слов и полу-слов). Проблема: MDMA не работает: инит сделал Кубом , вызов через HAL. Код стандартный и нет нужды его приводить здесь. Буфер кадра в AXI SRAM, дисплей на FMC, кеширование портов дисплея отключено (адреса 0xC0000000...0xC0010000). Дисплей чёрный - ничего не отрисовывает. Почему? Волнует специфика - может ли MDMA отрабатывать транзакции AXI SRAM => FMC ? Читал мануал, прямого ответа там на мой вопрос нет.
  6. STM32H743 MDMA

    Одна DMA-транзакция: не более 65535 байт за 1 раз. Пришлось бить на 3 равные части: LCD_H*LCD_W)<<1)/3 ((400*240 пикспелей) *2 байт) /3 = 64000 байт. По три раза(последний аргумент).
  7. Соглашусь, что форум отличный! Главное, чтобы модераторы следили за порядком и не сдавали позиции! Это один из немногих форумов, который очень полезный, благодаря очень компетентным участникам! И если модераторы будут пресекать соревнования в стиле "чей пукан более стальной", то этот форум останется полезным и никто не разбежится! Долой троллей с форумов! Ну и благодарность участникам форума, кто мне лично помог! И с наступающим Новым годом!
  8. Спасибо! Теперь я могу быть спокойным и искать другие пути решения.
  9. STM32H743 MDMA

    Приходилось использовать MDMA по причине того, что он может менять последовательность байт при передаче, что очень важно при пересылке буфера в LCD (иначе пришлосб бы менять байты вручную через _rev16). Всё исправно работает, ниже код. Правда, пришлось повозиться с настройками. static void MX_MDMA_Init(void) { /* MDMA controller clock enable */ __HAL_RCC_MDMA_CLK_ENABLE(); /* Local variables */ /* Configure MDMA channel MDMA_Channel7 */ /* Configure MDMA request hmdma_mdma_channel7_sw_0 on MDMA_Channel7 */ hmdma_mdma_channel7_sw_0.Instance = MDMA_Channel7; hmdma_mdma_channel7_sw_0.Init.Request = MDMA_REQUEST_SW; hmdma_mdma_channel7_sw_0.Init.TransferTriggerMode = MDMA_FULL_TRANSFER; hmdma_mdma_channel7_sw_0.Init.Priority = MDMA_PRIORITY_LOW; hmdma_mdma_channel7_sw_0.Init.Endianness = MDMA_LITTLE_BYTE_ENDIANNESS_EXCHANGE; //Меняем местами байты (для LCD) hmdma_mdma_channel7_sw_0.Init.SourceInc = MDMA_SRC_INC_HALFWORD; hmdma_mdma_channel7_sw_0.Init.DestinationInc = MDMA_DEST_INC_DISABLE; hmdma_mdma_channel7_sw_0.Init.SourceDataSize = MDMA_SRC_DATASIZE_HALFWORD; hmdma_mdma_channel7_sw_0.Init.DestDataSize = MDMA_DEST_DATASIZE_HALFWORD; hmdma_mdma_channel7_sw_0.Init.DataAlignment = MDMA_DATAALIGN_PACKENABLE; hmdma_mdma_channel7_sw_0.Init.BufferTransferLength = 2; //1 для BYTE, 2 для HALFWORD, 4 для WORD hmdma_mdma_channel7_sw_0.Init.SourceBurst = MDMA_SOURCE_BURST_SINGLE; hmdma_mdma_channel7_sw_0.Init.DestBurst = MDMA_DEST_BURST_SINGLE; hmdma_mdma_channel7_sw_0.Init.SourceBlockAddressOffset = 0; hmdma_mdma_channel7_sw_0.Init.DestBlockAddressOffset = 0; if (HAL_MDMA_Init(&hmdma_mdma_channel7_sw_0) != HAL_OK) { Error_Handler(); } } void SaI2xTransfer(void) { HAL_MDMA_PollForTransfer(&hmdma_mdma_channel7_sw_0,HAL_MDMA_FULL_TRANSFER,100); SaI2x((u8*)&BufferAndBorder[(1+160+2)+1],1+160+2,FilterBuffer,LCD_W<<1,160,120); SCB_CleanDCache(); HAL_MDMA_Start(&hmdma_mdma_channel7_sw_0,(u32)FilterBuffer,(u32)&LCD_DAT32,((LCD_H*LCD_W)<<1)/3,3); }
  10. Voice activity detection (VAD)

    "Любой каприз за ваши деньги" (c)
  11. Voice activity detection (VAD)

    AlexandrY, вы как-будто на другой планете живёте! ))) То, что для всех VAD, для вас - не VAD, а непонять что. Читаем википедию и видим: https://ru.wikipedia.org/wiki/Speex Вопросы? Меня волнует больше другой вопрос: сколько мозговых извилин у среднего индивидуума понадобится для этого, чтобы разработать надёжно работающее устройство по этому принципу? И сколько таких индивидуумов на планете существует?
  12. "Потому что гладиолус! ..." (c) Да тут всё понятно. Сделать это можно, но через большую ... (так, а где тут смайлик с поворачивающейся жопой? :) раньше был такой!)
  13. Так карты давно уже отформатированы на размер кластера 32 кБ программой SDFormatter! Но FatFs от этого быстрее не заработала. Потому что внутри неё идёт чтение секторов архаичными порциями по 512 байт даже в мультисекторной командой: ждём токена, выкачиваем 512 байт, 2 байта CRC, и так по кругу. Да и вообще, FatFS не учитывает размер кластера. Только сектор - минимальный и максимальный (обычно они равны) и интерфейс SDIO позволяет читать за один запрос целым блоком по 4, 8, 16 и 32 КБайта. При этом резко повышается скорость чтения, т.к. "накладных расходов" гораздо меньше. Не видал такого! В STM-ном коде от кало-куба идёт общение карты через 4-битный SDIO, но чтение порциями в мультисекторных командах там по-прежнему - по 512 байт Нет такого там чтобы сделать чтение 4 кбайт через SPI, везде идут SPI-чтения по 512 байт. Тем не менее, мультисекторное чтение даёт и в этом случае выигрыш в разы по сравнению с чтением по 1 сектору. Но речь шла о том как заставить карту выдать к примеру 4 кБайт данных, с минимум опросом одного токена + 2 байта ЦРЦ
  14. Для того чтобы другие системы засинхронизировать от прерывания по опустошению звукового буфера с заданным интервалом. Нужен определённый размер буфера или кратный целому числу от минимального размера. )) Нужен буфер на 480 или 512 семплов.
  15. Ого! 32 кГц семплрейт, что надо! Спасибо! P.S. хотя, не пойдёт. Рано радовался: Надо чтобы размер семплов был фиксированным и задан. Так что пока вижу Opus без вариантов + ресемплирование 48->32
  16. Voice activity detection (VAD)

    В моих цифровых радейках работает Включается передача по голосу + небольшая задержка перед выключением. Монотонный шум в виде шума машин, гудения куллеров компа, звука работающей вытяжки на кухне - тоже убирает. Пользователи довольны. Ну и конечно же рассказывать как портировать Speex или его часть исходников на МК я тут не собираюсь ! Речь о вот этом устройстве: https://vrtp.ru/index.php?act=categories&CODE=article&article=3660
  17. Opus отлично жмёт музыку ))) А RLE оказался лучше Хаффмана на 16-битных картинках (используется модифицированный RLE, который понимает что сжимать, а что оставлять)
  18. Opus. Поддерживает регулируемую длину фрейма при условии если выбран флаг CBR. Мои задачи решает! Жаль что нет 32 кГц семплрейта, прийдётся пересемплировать ручками 48->32 кГц
  19. Voice activity detection (VAD)

    А это что? И причем тут fixed point? Я на floating point его применял, в моих рациях прекрасно работает как VAD, так и подавитель шума. Своим глазам и ушам я верю больше, чем неизвестным сомневающимся на форумах. speex_s=speex_preprocess_state_init(FRAME,8000); speex_i=1; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_DENOISE,&speex_i); speex_i=-48; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_NOISE_SUPPRESS,&speex_i); speex_i=0; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_AGC,&speex_i); speex_f=8000; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_AGC_LEVEL,&speex_f); speex_i=0; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_DEREVERB,&speex_i); speex_f=.0; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_DEREVERB_DECAY,&speex_f); speex_f=.0; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_DEREVERB_LEVEL,&speex_f); speex_i=1; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_VAD,&speex_i); speex_i=80; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_PROB_START,&speex_i); speex_i=65; speex_preprocess_ctl(speex_s,SPEEX_PREPROCESS_SET_PROB_CONTINUE,&speex_i);
  20. Нет. HighSpeed доступен и при 3,3 V. Есть ещё более быстрый режим, и он требует 1,8V. У меня карты без проблем переводятся в HighSpeed при питании 3,3V и через SPI. Во всяком случае, я вижу прирост скорости. И ответ после переключения карты получаю положительный. И на запрос переключится в HighSpeed получаю добро от карты. s8 SDCARD_HighSpeed(void) /* ??? */ { u8 CCCR[64]; u8 crc[2]; //Проверяем, умеет ли карта HS режим { SDCARD_Select(); SDCARD_WaitNotBusy(); //CMD6 command static const u8 cmd[]={0x40|0x06 /* CMD6 */,0x00,0xFF,0xFF,0xF1 /* ARG */,(0x7F<<1)|1 /* CRC7 + end bit*/ }; SPI_TX((u8*)cmd,sizeof(cmd)); if(SDCARD_ReadR1()!=0x00) { SDCARD_Unselect(); return -1; } if(SDCARD_WaitDataToken(DATA_TOKEN_CMD6)<0) { SDCARD_Unselect(); return -2; } SDCARD_ReadBytes(CCCR,sizeof(CCCR)); SDCARD_ReadBytes(crc,sizeof(crc)); SDCARD_Unselect(); //Проверка бита SHS регистра карты CCCR if((CCCR[63-(400/8)]&0x01)!=0x01) return -3; } //Просим карту переключиться в HS режим { SDCARD_Select(); SDCARD_WaitNotBusy(); //CMD6 command static const u8 cmd[]={0x40|0x06 /* CMD6 */,0x80,0xFF,0xFF,0xF1 /* ARG */,(0x7F<<1)|1 /* CRC7 + end bit*/ }; SPI_TX((u8*)cmd,sizeof(cmd)); if(SDCARD_ReadR1()!=0x00) { SDCARD_Unselect(); return -4; } if(SDCARD_WaitDataToken(DATA_TOKEN_CMD6)<0) { SDCARD_Unselect(); return -5; } SDCARD_ReadBytes(CCCR,sizeof(CCCR)); SDCARD_ReadBytes(crc,sizeof(crc)); SDCARD_Unselect(); } return 0; }
  21. У меня стоит убунта второй осью, надо будет попробовать ))) А вообще, я давным давно написал файловый эксплорер на FatFs под винду для SD-карточек ))) Можно делать размер виртуального сектора любым, я делал 8 кБ - скорость на порядок возрастала, да! Но проблема в том, что отформатировать карту проблема - приходится под виндой тереть нулевой сектор, перевтыкать карту и только потом форматировать своими побрякушками. Иначе винда определяет логический диск и не даёт отформатировать его. Это очень пичально.. (( Что же они SPI режимы невзлюбили? Не всегда удаётся SDIO задействовать, по причине банальной занятости ножек контроллера на другие интерфейсы ))) А мультиплексировать и делить во времени тоже не вариант. Хаффман плохо жмёт ADPCM, на 18 % выигрыш. RAR ещё хуже жмёт. Для звука скорее всего лучше будет только сжатие с потерями качества. А вот картинку в 16 бит Хаффман ужал в 5 раз почти ( RAR лучше, но он более ресурсоёмкий).
  22. Эксперимент выявил следующее: Чтение 2048 секторов (8 МБ) мультиблочной командой чтения занимает 3,6 секунды. Причем класс скорости не важен - 4 или 10. Всё читается одинаково, ибо этот класс скорости описывает операции записи, которые лично мне в данной задаче неинтересны. Выходит 2,2 МБайт/с Кеширование секторов в функции move_window() у Чана (FatFS) ни к чему не привело. Кеширование делал по принципу индексации секторов и проставлению лайков к ним если при чтении кеша они находятся. Заполнение кеша происходит от начала к концу и в первую очередь по принципу "слабого звена" - чем меньше лайков у индекса (редко используется) тем выше вероятность замены. Считал сектор - закешируй и поставь ему лайк..... Дальнейшее ускорение я вижу за счёт небольшого сжатия - добавить RLE или Хаффмана для исходных данных - картинки в формате 16 бит и звук -ADPCM. На счёт размера блоков карты памяти - там от 1 до 512, карт с бОльшим размером блока я не видел. HxD под виндами видит сектор 512 байт. На счёт установить буфер в FatFs больше 512 - это приведет к тому что надо будет чтение 1 сектора имитировать чтением сразу 4-х. Под виндой не закинешь на карту ничего, если самому FatFS под виндой не использовать и писать работу с диском через IOCTL (такую штуку я написал давно, но распостранения она не получила)
  23. Прироста в скорости переход с LFN на 8.3 не дал. Флажок в ffconf LFN выставлен в 0. Тут пишут, что мультиблочное чтение всёравно должно идти порциями по 512 байт и нужно ждать дата-токена и считывать 2 байта CRC. Разом не считаешь без дата-токена - нужно ждать. А это плохо. https://www.avrfreaks.net/forum/writeread-multiple-blocks-sd-card-0 Read multiple blocks is same as above except: Send READ_MULTIPLE_BLOCK command to card with address, number of blocks etc Repeat for number of blocks { Poll card for 0xFE (data token) Receive the 512 bytes. receive 2 CRC bytes } + READ END CMD
  24. Не могли бы вы осветить этот момент подробнее? Пробовал читать больше чем по 512 байт: по 1024 и по 4096 - файловая система работает некорректно с такими длинами чтений. Интересует SDCARD_ReadData(u8* buff) Там после каждых 512 байт надо делать опрос SDCARD_WaitDataToken(DATA_TOKEN_CMD18)<0) , иначе неправильно работает. Прорабатываю вариант без LFN, имена директорий и файлов в формате 8.3