LINUX.ORG.RU

Почему частота генерируемого аудиозвука DAC остается неизменной?

 , , ,


0

0

Сап двач лор. Есть такой код для stm32f1x: (cmsis + spl)

#include <stm32f10x.h>
#include <stm32f10x_rcc.h>
#include <stm32f10x_gpio.h>
#include <stm32f10x_dac.h>
#include "sine_wave.c"

void Delay(uint32_t nTime);
void dac_init();

int main(void){

    dac_init();

    // Configure SysTick Timer
    if(SysTick_Config(SystemCoreClock / 1000))
        while(1);

    while(1) {
        for (int i = 0; i < ARR_SIZE; i++) {
            DAC_SetChannel1Data(DAC_Align_12b_R, a441[i]);
            Delay(1);
        }
    }
}

void dac_init()
{
    GPIO_InitTypeDef GPIO_InitStructure;
    DAC_InitTypeDef DAC_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC , ENABLE);

    GPIO_StructInit(&GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // DAC channel1 Configuration

    DAC_StructInit(&DAC_InitStructure);
    DAC_InitStructure.DAC_OutputBuffer = DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1 , &DAC_InitStructure);

    // Enable DAC

    DAC_Cmd(DAC_Channel_1 , ENABLE);
}

// Timer code
static __IO uint32_t TimingDelay;

void Delay(uint32_t nTime){
    TimingDelay = nTime;
    while(TimingDelay != 0);
}

void SysTick_Handler(void){
    if(TimingDelay != 0x00)
        TimingDelay --;
}

Я заливаю его на платку и подключаю к PA4 аудиоусилитель, а к нему - динамик. Цель - воспроизводить звуки разной частоты/высоты.

Так вот, звук реально воспроизводится. Но проблема в том, что частота этого звука неизменно остается где-то 1980 Гц (нота B6), когда я меняю длительность delay.

Мне кажется, что при более длинной задержке, частота должна уменьшаться (волна «растягивается») и тон становиться ниже. Но тон неизменяем.

Что посоветуете, может я ошибаюсь где-то?


Аййййй только что возникла идея. У меня же волна идеально-синусоидная и константная в «sine_wave.c». Типа такого:

int16_t a441[] = {
	1024,
	1056,
	1088,
	1119,
/*...*/

Может ее надо заново генерировать всякий раз, когда я хочу изменить частоту ноты. Сейчас попробуем.

x86-
() автор топика

Если a441 это намёк на частоту дискретизации 44.1kHz то ты что-то делаешь неправильно выдавая отсчеты с частотой не более 1kHz

cobold ★★★★★
()
Ответ на: комментарий от cobold

Пока нет, это переходная стадия. На следующем этапе я переведу его на 44.1 кГц.

x86-
() автор топика

А, дошло! Чтобы генерировать различные ноты, нужно возиться со всякими гармониками и регенерировать семплы волн через раз. Я лучше попробую брать готовые WAV-файлы, парсить и брать семплы оттуда. Все, тему отмечаю решенной.

x86-
() автор топика

проблема в том, что частота этого звука неизменно остается где-то 1980 Гц

У вас задержка регулируется прерыванием systick, которое по дефолту срабатывает раз в миллисекунду, то есть частоту выше 1 кГц таким способом не проучить в принципе. Если у вас частота выше, значит либо вы что-то шаманили с systick (надеюсь, что нет, потому что им пользуются другие компоненты), либо Delay работает неправильно, а частота задается готовностью ЦАП и внутренними задержками ST-HAL.

В любом случае 1 кГц для генерации звука это маловато, поэтому имеет смысл использовать обычные таймеры. Например, настраиваете TIM4 на срабатывание с частотой скажем 100 кГц, в прерывании подставляете DAC1->DR значение из массива. Это простейший вариант. Более простой, чем сейчас у вас.

Вариант попрямее: снова настраиваем таймер и ЦАП, но с учетом DMA. Пусть по событию таймера DMA самостоятельно берет значение из массива и кладет в ЦАП. Такая штука будет работать независимо от ядра. Единственное что частоты выше (F_CPU / sizeof(arr) / 4) вы не получите. Вообще, это тоже лечится, но чуть сложнее. И не уверен, что это лечится чисто аппаратными средствами без костылей.

В общем, начните с изучения обычных таймеров и их прерываний.

COKPOWEHEU
()
Ответ на: комментарий от x86-

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

t184256 ★★★★★
()
Ответ на: комментарий от COKPOWEHEU

В любом случае 1 кГц для генерации звука это маловато, поэтому имеет смысл использовать обычные таймеры. Например, настраиваете TIM4 на срабатывание с частотой скажем 100 кГц, в прерывании подставляете DAC1->DR значение из массива. Это простейший вариант. Более простой, чем сейчас у вас.

Да, вы правы, это была просто проба пера так сказать. Сейчас код уже переведен на таймеры с DMA и частотой 44.1 кГц.

x86-
() автор топика
Ответ на: комментарий от t184256

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

Для идеальной константной синусоидной волны с ровно N семплами, изменение скорости пробега по волне генерируемый тон не меняет. Для получения других тональностей и обертонов нужны более сложные модификации волны, с преобразованиями гармоник и прочей математикой. Ну, по крайней мере это то что я себе представляю.

x86-
() автор топика
Ответ на: комментарий от x86-

Как то сложно ты себе это представляешь. Например, рассчитай звук с частотой 1 кГц, сколько семплов у тебя уйдет на 1 период при выбранной дискретизации?

Дело в том что всё тут так просто, что немного смутился даже, может задача сложнее чем «Цель - воспроизводить звуки разной частоты/высоты»

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Как то сложно ты себе это представляешь. Например, рассчитай звук с частотой 1 кГц, сколько семплов у тебя уйдет на 1 период при выбранной дискретизации?

Количество семплов рассчитать не сложно, сложнее рассчитать значения самих семплов.

https://present5.com/tema-zvukovoj-analizator-1-prostye-i-slozhnye-zvuki/

Большинство звуков не идеально синусоидны, а имеют гармонические искажения.

x86-
() автор топика
Ответ на: комментарий от x86-

А, вообще я сейчас читаю вики, и, судя по всему, все действительно гораздо проще: сгенерировать тона разной высоты можно и с помощью простых синусоид без искажений:

https://en.wikipedia.org/wiki/Harmonic#Partials,_overtones,_and_harmonics

, а различие будет только в количестве семплов/циклов в секунду. Все же ты прав. Но, ладно уже, пойду ленивым путем с WAV-файлами.) Там все за меня сгенерировано.

x86-
() автор топика
Ответ на: комментарий от x86-

Для идеальной константной синусоидной волны с ровно N семплами, изменение скорости пробега по волне генерируемый тон не меняет.

Скажи честно, ты в состоянии измененного сознания?

Надо что-то тебе в коммент написать во избежания повторения таких дискуссий, есть предложения?

t184256 ★★★★★
()
Ответ на: комментарий от t184256

Нет. Я где-то утверждаю, что профи? Наоборот, если я в чем-то заблуждаюсь, лучше поправь по-существу.

x86-
() автор топика
Последнее исправление: x86- (всего исправлений: 1)
Ответ на: комментарий от x86-

Для воспроизведения синуса повышенной/пониженной частоты без лишних гармоник надо воспроизводить синус быстрее/медленнее. Будет синус другой частоты. Если предгенерируешь с частотой много больше желаемых, можешь даже с интерполяцией не задуряться, брать nearest с округлением куда угодно.

t184256 ★★★★★
()
Последнее исправление: t184256 (всего исправлений: 1)
Ответ на: комментарий от x86-

10000 + 10000 * math.sin((2 * math.pi * i * 1000) / 44100) # вот тебе синус 1 кГц для дискретизации 44.1 кГц, амплитуда 10К

Период сигнала составит примерно 44 семпла

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 1)
Ответ на: комментарий от I-Love-Microsoft

Спасибо, хотя да, у меня уже есть отдельный модуль для генерации синусов.

x86-
() автор топика
Ответ на: комментарий от x86-

Для идеальной константной синусоидной волны с ровно N семплами, изменение скорости пробега по волне генерируемый тон не меняет.

Как это не меняет. Звук это в конечном итоге колебания чем они чаще в единицу времени тем выше тон чем они реже тем выше.

Звук для тебя это uint8_t array[SAMPLE_SIZE] а тон это то какой Delay(ns) ты выставляешь между обработкой каждого array[i++] элемента. Ну это если совсем всё в лоб. Ну или я чего то не понял

SystemCoreClock / 1000

Я в руках STM32 не держал но по моему тут не 1000, а константу CLOCKS_PER_SEC или типа того

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Мне пока трудно понять в чем затрудняется ТС, но помочь хочется. Я конечно полупрофессионально занимаюсь цифровой обработкой сигналов, думаю подскажу если пойму задачу

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

Не, проблема уже решена и вопрос отвечен.

x86-
() автор топика
Ответ на: комментарий от x86-

Ладно. Ты дверной звонок делаешь? Типа кнопка жмак и оно тринь-тилинь:-золотая-чаша-золотаяяяяя-напоняет-ароматом-чаяяяя-дом-вкотором-счатье-обитааааеееет-золотаая-чаша-золотаааяяяя GOTO тилинь. :D

LINUX-ORG-RU ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

:D. Не, замахиваюсь на создание небольшого плеера. Одноканальный, поддерживать будет только WAV и 44.1кгц.

x86-
() автор топика
Ответ на: комментарий от x86-

А, ну норм, правильно без лишних замашек. На основе можно и звонок дверной сделать :D А чё нет то. После плеера можно научить читать из SD карточки wav файлы. Или вместо динамика вставлять инфракрасный диод, а на пк тоже на STM сделать приёмник который по usb цепляется к компу принимает сигналы с «звонка» и пишет их в /dev/чётотам где твоя хостовая программа читает поток и если он не пуст воспроизводит тебе звук в наушники. ыгыгыгы

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от LINUX-ORG-RU

Файлы как раз и будут читаться с SD-карты. А вот вторая идея забавная, стоит попробовать. :-D

x86-
() автор топика

Почему частота генерируемого аудиозвука DAC остается неизменной?

Отвечу на сабж свою версию: главное требование это чтобы частота дискретизации ЦАП была как минимум вдвое больше чем частота самого высокочастотного компонента спектра сигнала. Если построить спектр, то можно видеть почему есть такое требование

Поэтому, чтобы покрыть максимум спектра слышимого звука, выбрали частоту 44 КГц. Удобно если она постоянная и неизменная, в нее можно вложить любой звуковой сигнал

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от x86-

В галерею потом выкладывай результат. С видосом. Когда запустишь массовое производство с тебя 25% от продажи каждого устройства за составление технического плана и соблюдение патента на изобретение которое я прямо сейчас оформляю, вот юрист подписал бумаги. Нотариально заваренный срин есть. Через неделю придёт бумага с патентного бюро и я в шоколаде =) Бабо еси чё как накопится миллион так я и скажу куда слать. Доход менее миллиона весь твой. Ну вроде всё. Успехов!

LINUX-ORG-RU ★★★★★
()
Последнее исправление: LINUX-ORG-RU (всего исправлений: 1)
Ответ на: комментарий от I-Love-Microsoft

главное требование это чтобы частота дискретизации ЦАП была как минимум вдвое больше чем частота самого высокочастотного компонента спектра сигнала.

А, так вот оно что. Спасибо, буду знать.

x86-
() автор топика

Подсказываю простейший способ:

1. Генеришь таблицу для синусоиды (лучше всего ее на компьютере сгенерировать и сохранить в виде массива в секции text).

2. Запиливаешь таймер с DMA. Таймер пинает DMA и меняет значение ЦАПа.

3. Меняя частоту таймера, ты автоматом меняешь частоту синусоиды.

Вуаля!

anonymous
()
Ответ на: комментарий от x86-

замахиваюсь на создание небольшого плеера. Одноканальный, поддерживать будет только WAV и 44.1кгц.

Так для этого синусоиды не нужны. wav содержит мгновенные значения, достаточно их считать и вывести в ЦАП.

Кстати, лучше даже не в ЦАП, а в ШИМ, чтобы усиливать проще было.

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

++

Заводить двойной буфер. Пока один заполняешь, из второго DMA в ЦАП или ШИМ нужные значения выводит. 8-битный wav можно напрямую выплевывать без всякой математики. Только частоту стоит ограничить 22кГц.

anonymous
()
Ответ на: комментарий от COKPOWEHEU

wav содержит мгновенные значения

Ну а если кто-то хочет в этом убедиться, может запустить простенький конвейер:

$ tail -c +44 res.wav | head -c 4410 | hexdump -ve '1/1 "%.2u\n"' | feedgnuplot --lines

44 это размер заголовка 4410 - количество точек для отображения (иначе уж слишком каша получается) «.2u\n» - форматная строка. В моем случае использовался сгенерированный мной же файл с одним каналом и разрешением 1 байт, но если эту строку поменять, можно смотреть и другие файлы

COKPOWEHEU
()
Ответ на: комментарий от COKPOWEHEU

Так для этого синусоиды не нужны. wav содержит мгновенные значения, достаточно их считать и вывести в ЦАП.

Знаю, просто захотелось погенерировать синусоид чтобы увидеть как все работает. А дальше уже буду с wav считывать готовые фрагменты семплов в буфер и выводить в DAC.

x86-
() автор топика
Ответ на: комментарий от COKPOWEHEU

Вот хотел что-то умное с работы написать, а какой-то мудак-мудератор мне обе прокси, через которые на работе инет идет, забанил!

Я б вообще убивал за бан по IP! Это ж сразу несколько тысяч человек лишаются возможности постинга на ЛОРе!!!

anonymous
()
Ответ на: комментарий от x86-

Хм… Да этож самые основы основ. Теорема Найквиста-Шенона гласит, что для того чтобы без ошибочно восстановить форму сигнала после дискретизации, частота этой самой дискретизации должна быть как минимум в два раза больше самой высокой частоты спектра сигнала. Поэтому кстати и прижились 44,1кГц, ибо человеческий слух перестаёт воспринимать частоты выше ~ 22кГц.

anonymous
()
Ответ на: комментарий от anonymous

Да, надо бы немного наверстать упущеные книги по этой теме. Я в ней совсем юзверь.

x86-
() автор топика
Ответ на: комментарий от anonymous

человеческий слух перестаёт воспринимать частоты выше ~ 22кГц.

А если еще вспомнить, что большая часть звуков составляет порядка 1 кГц, понятны и более низкие частоты.

Скажем, для воспроизведения голоса хватает даже 4 кГц - с искажениями, конечно, но вполне разборчиво.

COKPOWEHEU
()
Ответ на: комментарий от anonymous

Смотри, где-то среди твоих тысяч не интересующихся ЛОРом человек ходит один троллюга =)

t184256 ★★★★★
()
Ответ на: комментарий от anonymous

Ты тоже потише, аудиофилы с их 100500Гц нужны диджеям.

t184256 ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.