|
|
  |
Работа со звуком в программе с операционной системой |
|
|
|
Jan 29 2013, 17:38
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 20-02-09
Пользователь №: 45 138

|
Здравствуйте, господа! Понадобилось в проекте с операционной системой RL-ARM RTX проигрывать wav-файл с карты памяти. Подскажите пожалуйста, как лучше это реализовать. Само устройство сделано на базе LPC2378 (есть подключенная внешняя ОЗУ), звук выводится через ЦАП микроконтроллера. Я посмотрел, для вывода требуется частота отсчетов минимум 8 кГц, но системный тик RTX сейчас 1 милисекунда. Как поступить? Или уменьшать время системного тика, или каким-то образом задействовать еще один таймер и отправлять данные очередного отсчета из обработчика его прерывания? Заранее благодарен
|
|
|
|
|
Jan 30 2013, 01:37
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (stepper88 @ Jan 30 2013, 01:38)  Здравствуйте, господа! Заранее благодарен Добрый день! На мой взгляд лучше бы внешний кодек на I2S, и DMA'ем гнать в него поток из внешней RAM) Но поскольку Вы уже использовали АЦП этого МК (не лучший вариант, к сожалению, т.к. если мне память не изменяет, DMA не имеет доступа к ЦАПу), то, наверно, действительно только таймер. В высокоприоритетную задачу вряд ли звуковой поток поставить. Хотя попробовать можно.
--------------------
Выбор.
|
|
|
|
|
Jan 30 2013, 08:01
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 28-06-07
Из: Israel
Пользователь №: 28 763

|
Цитата(ar__systems @ Jan 30 2013, 08:50)  Нормальный звук врядли на нем удастся сделать. Так не музыку же собираются играть, раз там Fs=8kHz. Цитата DMA не имеет доступа к ЦАПу При Fs=8kHz и не надо никакого DMA. Можно завести таймер на 8кгц и сделать два буфера, в один считывать с карты памяти, со второго - по прерыванию таймра выводить в ЦАП. По концу буфера, буфера меняются местами.
|
|
|
|
|
Jan 30 2013, 08:23
|

Познающий...
     
Группа: Свой
Сообщений: 2 963
Регистрация: 1-09-05
Из: г. Иркутск
Пользователь №: 8 125

|
QUOTE (Allregia @ Jan 30 2013, 17:01)  Можно завести таймер на 8кгц Так моя и не спорит, понимает, что можно  Вот только дергать ARM каждые 125 мкс как-то не камильфо. Нет, можно, но я, как уникальная личность, не сторонник такого подхода  Желание эмулировать интерфейсы программно (где времянка играет основнополагающую роль) у меня еще отпало лет 6 назад Гм... как абсурдная идея гнать аудио в FIFO USART, а на выходе конвертировать его сдвиговым регистром в параллельный код  Я понимаю, печатка уже сделана. Автор, когда придете к окончательному решению, будьте добры, расскажите нам, как и что  Аж интересно стало!
--------------------
Выбор.
|
|
|
|
|
Jan 30 2013, 14:06
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 20-02-09
Пользователь №: 45 138

|
Цитата(haker_fox @ Jan 30 2013, 14:23)  Автор, когда придете к окончательному решению, будьте добры, расскажите нам, как и что  Аж интересно стало! Простите пожалуйста, что не ответил сразу. На работе интернет тормозит сегодня жутко. Пока что сделал сегодня только распаковку файла wav и вывод отсчетво на терминал. У меня вопрос насчет таймера - если я сделаю прерывания с частотой 8 кГц это не порушит операционную систему? Просто устройство должно реализовывать госовое меню по телефону и охота отлавливать реакцию модема - повесил ли пользователь трубку, а может быть, нажал кнопку. С кодеком, к сожалению не получится - плата уже сделана и не хочется сильно вносить изменения в схемотехнику. За идею с буферами спасибо отдельное - вполне возможно, что тоже пробовать буду.
|
|
|
|
|
Jan 30 2013, 14:20
|

Гуру
     
Группа: Свой
Сообщений: 2 957
Регистрация: 19-09-06
Из: Москва
Пользователь №: 20 514

|
Цитата(stepper88 @ Jan 30 2013, 18:06)  У меня вопрос насчет таймера - если я сделаю прерывания с частотой 8 кГц это не порушит операционную систему? Просто устройство должно реализовывать госовое меню по телефону и охота отлавливать реакцию модема - повесил ли пользователь трубку, а может быть, нажал кнопку. вы же используете голосовые функции модема? что там к вам от него валится? Если поток валится, как анализируете? я когда-то делал подобное, с использованием БПФ, но это было на PC Мне от модема валился оцифрованный поток, я его просто БПФ скармливал и выделял КПВ оттуда
|
|
|
|
|
Jan 30 2013, 16:13
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 20-02-09
Пользователь №: 45 138

|
Цитата(toweroff @ Jan 30 2013, 20:20)  вы же используете голосовые функции модема? что там к вам от него валится? Если поток валится, как анализируете? На схеме распаяли апаратный декодер DTMF - думаю или с него брать данные, или же встроенный DTMF-декодер модема (модем Quectel M10) попробую запрячь
|
|
|
|
|
Feb 1 2013, 06:49
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 20-02-09
Пользователь №: 45 138

|
Цитата(toweroff @ Jan 31 2013, 00:25)  А как собираетесь отслеживать то, что пользователь повесил трубку? Когда пользователь кладет трубку, модем выдает NO CARIER и как раз это хочу отлавливать в другой задаче.
|
|
|
|
|
Feb 9 2013, 07:40
|
Участник

Группа: Участник
Сообщений: 43
Регистрация: 20-02-09
Пользователь №: 45 138

|
Прошу прощения, что долго не заходил в тему. На данный момент изобразил две функции воспроизведения wav-файла. Первая была более простой - там просто между отправками отсчетов на цап запускается таймер и отмеряет задержку - прерывание там не используется. Код memcpy(&size, &buffer[4],4); while (size>128) { fread(buffer, sizeof(char), 128, f); size=size-128; for (t=0;t<128;t++) { DACR=buffer[t]<<8; T1_delay(86); } result=os_evt_wait_or(0x003E, 0); if (result==OS_R_EVT) { fclose(f); return; } } fread(buffer, sizeof(char), size, f); for (t=0;t<size;t++) { DACR=buffer[t]<<8; T1_delay(86); } result=os_evt_wait_or(0x003E, 0); if (result==OS_R_EVT) { fclose(f); return; } fclose(f); result=os_evt_wait_or(0x003E, timeout); } Второй вариант использует прерывания от таймера и два буфера Код memcpy(&size, &buffer[4],4); fread(buffer, sizeof(char), 256, f); size=size-256; T1TCR=0x01; while (size>128) { switch (empty) { case 0: break; case 1: fread(buffer, sizeof(char), 128, f); empty=0; size=size-128; break; case 2: fread(&buffer[128], sizeof(char), 128, f); empty=0; size=size-128; break; } result=os_evt_wait_or(0x003E, 5); if (result==OS_R_EVT) { T1TCR=0; fclose(f); return; } } switch (empty) { case 0: break; case 1: fread(buffer, sizeof(char), 128, f); empty=0; size=size-128; break; case 2: fread(&buffer[128], sizeof(char), 128, f); empty=0; size=size-128; break; } result=os_evt_wait_or(0x003E, 5); if (result==OS_R_EVT) { T1TCR=0; fclose(f); return; } Обработчик прерывания Код void T1_Handler (void) __irq { T1IR=0x01; switch (t) { case 128: empty=1; break; case 0: empty=2; break; } DACR=buffer[t++]<<8; VICVectAddr = 0; // Acknowledge Interrupt } Решил вместо двух массивов использовать один, но поочередно записывать в первую и вторую половины массива. Насчет "поумневших" модемов в моем случае оказалось достаточным включить встроенный декодер DTMF модема и он по нажатию каждой кнопки выплевывал сообщение. P.S. прилагаю файл wav.c - в нем функция play_wav() реализует проигрывание файла без использования прерывания от таймера, функция play_wav_int() соответственно с использованием
Прикрепленные файлы
wav.rar ( 1.65 килобайт )
Кол-во скачиваний: 10
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|