User Tag List

Страница 4 из 4 ПерваяПервая 1234
Показано с 31 по 32 из 32

Тема: BEEP (freq, ms) для бипера, AY и даже Windows

  1. #31

    Регистрация
    24.08.2007
    Адрес
    Днепропетровская обл.
    Сообщений
    1,681
    Спасибо Благодарностей отдано 
    2,714
    Спасибо Благодарностей получено 
    170
    Поблагодарили
    130 сообщений
    Mentioned
    1 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Есть ли формула пересчёта высоты тона из команды BEEP в частоту в герцах? Хочу воспроизводить вот этой процедурой:
    Код:
    #include <windows.h>
    
    // описание заголовка файла WAV
    struct WAVHEADER
    {
    	char	sigRIFF[4];	 // должно быть равно "RIFF"
    	DWORD   sizeRIFFch;	 // размер чанка RIFF
    	char	sigWAVE[4];	 // должно быть равно "WAVE"
    	char	sigFMT[4];	  // должно быть равно "fmt "
    	DWORD   sizeFMTch;	  // размер чанка FMT
    	WORD	wFormatTag;	 // категория формата, для PCM = 1
    	WORD	wChannels;	  // кол-во каналов: 1-моно 2-стерео
    	DWORD   dwSamplesPerSec;// кол-во сэмплов в сек.
    	DWORD   dwAvgBytesPerSec;// среднее число байт в сек
    	WORD	wBlockAlign;	// выравнивание данных в дата-чанке
    	WORD	wBitPerSample;  // бит в сэмпле
    	char	sigDATA[4];	 // должно быть равно "data"
    	DWORD   sizeDATAch;	 // размер data-чанка
    };
    
    
    void Beep(DWORD dwFrequency, DWORD dwMilliSeconds)
    {
    	// частота дискретизации = 44100 Гц
    	// кол-во бит на сэмпл = 8
    	// если требуемая частота > 44100 или равна нулю, то выходим
    	if(!dwFrequency || dwFrequency>44100)
    		return;
    
    	// длина дорожки в байтах
    	DWORD numSamples = 44100 / dwFrequency;
    	
    	// выделяем память под дорожку
    	DWORD size = sizeof(WAVHEADER) + numSamples;
    	void *buff = new char[size];
    
    	if(buff) {
    	
    		// заполняем WAV-header
    		WAVHEADER *head = (WAVHEADER*)buff;
    		strcpy(head->sigRIFF, "RIFF");
    		strcpy(head->sigWAVE, "WAVE");
    		head->sizeRIFFch = size - 8; 
    		strcpy(head->sigFMT, "fmt ");
    		head->sizeFMTch = 16;
    		head->wFormatTag = 1;
    		head->wChannels = 1; // моно
    		head->dwSamplesPerSec = 44100;
    		head->dwAvgBytesPerSec = 44100;
    		head->wBlockAlign = 1;
    		head->wBitPerSample = 8;
    		strcpy(head->sigDATA, "data");
    		head->sizeDATAch = size;
    
    		// заполняем дорожку периодом синуса
    		BYTE *samples = (BYTE*)(head+1);
    		for(DWORD i=0; i<numSamples; i++)
    			samples[i] = BYTE(255*sin(6.28*double(i)/double(numSamples)));
    
    		// проигрываем звук
    		PlaySound((LPCWSTR)buff, 0, SND_ASYNC|SND_LOOP|SND_MEMORY);
    
    		// ждём заданное количество миллисекунд
    		Sleep(dwMilliSeconds);
    
    		// останавливаем звук
    		PlaySound(0, 0, SND_ASYNC);
    
    		delete buff;
    	}
    }
    Кто может сказать: правильной ли частоты звуки генерирует эта процедура? Мне кажется, она фальшивит. Как точно это проверить в домашних условиях?

    P.S. Beep из WinAPI не годится - её поддержка есть не на всех версиях винды: в старых виндах она воспроизводит на бипер, в новых на звуковуху, на 64-битной висте/XP она ничего не делает.

  2. #31
    С любовью к вам, Yandex.Direct
    Размещение рекламы на форуме способствует его дальнейшему развитию

  3. #32

    Регистрация
    08.05.2007
    Адрес
    Dnepropetrovsk
    Сообщений
    1,089
    Спасибо Благодарностей отдано 
    281
    Спасибо Благодарностей получено 
    70
    Поблагодарили
    49 сообщений
    Mentioned
    3 Post(s)
    Tagged
    0 Thread(s)

    По умолчанию

    Привет.
    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    Есть ли формула пересчёта высоты тона из команды BEEP в частоту в герцах?
    насчёт команды BEEP точно не знаю. Что-то помню о том, что высота тона для BEEP задаётся в полутонах относительно базы. А раз так - то вот формула равномерной темперации из теории:

    f = 440*2^(n/12)

    где f - частота в герцах;
    n - номер ноты в полутонах относительно "Ля" первой октавы, которая имеет точно заданную частоту 440Гц. Номер этой ноты n=0. Для "До" второй октавы будет n=3 и т.д. Для более низких нот n отрицательно.
    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    Хочу воспроизводить вот этой процедурой:
    Процедура плохая, содержит ошибки и другие недочёты.

    1) Частота задаётся целым числом. Для нот это не годится, дробной частью перенебрегать нельзя, иначе будет фальшивить. Также при вычислениях не очень хорошо отрабатываются случаи округления дробных чисел. Опять-таки приводит к фальши.

    2) Используется 8 бит разрешение, что приводит к шуму квантования

    3) Ошибка: отсчёты сигнала для 8-битного файла являются беззнаковыми числами. Из формулы, где синус, выходят и отрицательные. В результате вместо синусоидального получается сигнал страшной формы, с огромными гармоническими искажениями.

    Дальше не проверял, могу дать пару советов:

    1) Очевидно, функция PlaySound воспроизводит wav-файл. Приведённая процедура создаёт в памяти образ wav-файла с сигналом. Альтернативный вариант - создать wav-файл с требуемым звуком в звуковом редакторе (Audacity и т.п.), загрузить в память и воспроизводить с помощью PlaySound.

    2) Функция PlaySound декларирует возможность зацикливания звука. Но не исключено, что зацикливание производится неидеально, со вставлением между циклами посторонних данных или обрезанием цикла до его фактического завершения. Дело в том, что PlaySound рассчитана на воспроизведение достаточно длинных файлов (1 секунда и более), где щелчки при зацикливании некритичны. В данной же процедуре генерируется только один или небольшое число периодов сигнала; любые неточности при зацикливании могут сильно исказить частоту и внести другие искажения.

    Вот формула для генерации синусоидального сигнала заданной частоты:
    y = sin(2*pi*f*t)

    где t - время, в секундах; f - частота в герцах; pi~=3.1415926... .

    Если частота дискретизации, к примеру, равна 44100, то:

    t[i] = i/44100.0;

    При зацикливании нужно обращать особое внимание, чтобы выдержать точный период синуса, иначе неизбежны гармонические искажения.

    Я как-то делал генератор синусоидальных сигналов следующим образом. Рассчитал один период синуса очень низкой частоты (0.1Гц) - 10 секунд. Получилось 10*44100 сэмплов. После этого генерировал куски синусов произвольной частоты следующим образом:
    Код:
    int j=0;
    int dj = lround(f*10); // f - frequency
    for(i=0; i<n; i++)
    {
        y[i] = x[j];
        j += dj;
        if(j >= 10*44100)
            j -= 10*44100;
    }
    где n - желаемая длительность сгенерированного сигнала, в сэмплах; x[] - таблица синуса 0.1Гц, 10 секунд; y[] - сгенерированный сигнал.

    В строке с if() производится зацикливание таблицы.

    Программа быстрая, но имеет недостаток - разрешение составляет всего 0.1Гц, что может быть недостаточно для музыки. Есть и другие способы, более эффективные по памяти и с более высоким разрешением по частоте.

    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    Как точно это проверить в домашних условиях?
    На мобилку скачать приложение - спектральный анализатор или анализаторы высоты тона (обучение пению, настройка музыкальных инструментов и т.п.).

    Ещё вариант - любым способом (мобилка, магнитофон) записать звук с компьютера в wav-файл, потом загрузить его в звуковой редактор и там анализировать.
    Цитата Сообщение от Oleg N. Cher Посмотреть сообщение
    P.S. Beep из WinAPI не годится
    Во всех версиях винды, начиная с 95, есть интерфейс "Windows Multimedia Audio" (mmsystem.dll). Нужные тебе функции:
    waveOutOpen
    waveOutPrepareHeader
    waveOutWrite
    waveOutPause
    waveOutRestart

    Это API для воспроизведения данных в реальном времени. Если разберёшься - работает очень хорошо. Рекомендую. Сам всегда пользовался.

    Этот пользователь поблагодарил Barmaley_m за это полезное сообщение:

    Oleg N. Cher(13.10.2020)

Страница 4 из 4 ПерваяПервая 1234

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Похожие темы

  1. Усилитель для бипера...
    от Quest в разделе Звук
    Ответов: 17
    Последнее: 29.03.2013, 16:58
  2. MISTER BEEP – Z80
    от breeze в разделе Музыка
    Ответов: 2
    Последнее: 09.01.2012, 13:54
  3. My Beep Song....
    от Voxel в разделе Музыка
    Ответов: 25
    Последнее: 05.07.2010, 11:28
  4. новый трекер для бипера
    от alone в разделе Музыка
    Ответов: 2
    Последнее: 22.09.2009, 04:16
  5. Новости от Mr.Beep !!
    от breeze в разделе Музыка
    Ответов: 3
    Последнее: 29.01.2009, 01:23

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •