C++Builder
Начало
Форум
Помощь
Войти
Регистрация
C++Builder
>
Forum
>
Вопросы программирования
>
Общие вопросы программирования в C++Builder
>
Как избавиться от пауз в генераторе НЧ
Страниц: [
1
]
Вниз
Печать
Автор
Тема: Как избавиться от пауз в генераторе НЧ (Прочитано 2745 раз)
Sergey1985
Участник
Сказали спасибо: +8/-1
Offline
Сообщений: 310
Как избавиться от пауз в генераторе НЧ
«
:
11 Январь 2014, 09:58:04 »
Уважаемые программеры. Помогите разобраться в одном щекотливом вопросе. У меня возникают щелчки в генераторе звуковой частоты (на 400 Гц). Привожу код программы. И еще я не пойму как можно задать форму сигнала во втором канале? ПОМОГИТЕ ПОЖАЛУЙСТА
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit1.h"
#include
#include
#include "Unit2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
WAVEFORMATEX wfx; // структура формата данных
HWAVEOUT sound_out_handle; // описатель устройства вывода
WAVEHDR hdr; // спец структура
HANDLE hEvent;
int i,j,l;
double k;
TSound *t;
int amp;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
t = new TSound(true);
amp = 32767;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
MMRESULT p;
// Формат звуковых данных
wfx.wFormatTag = WAVE_FORMAT_PCM;
// Количество каналов
wfx.nChannels = 1;
// Частота дискретизации (возможны значения 8000, 11025, 22050, 44100)
wfx.nSamplesPerSec = 8000;
// Количество бит в одной выборке (для WAVE_FORMAT_PCM 8 или 16)
wfx.wBitsPerSample = 16;
// Выравнивание блока (для WAVE_FORMAT_PCM равен wBitsPerSample/8*nChannels)
wfx.nBlockAlign = wfx.wBitsPerSample/8*wfx.nChannels;
// Количество байт в секунду
wfx.nAvgBytesPerSec = wfx.nSamplesPerSec*wfx.nBlockAlign;
// Размер дополнительной информации
wfx.cbSize = 0;
hEvent = CreateEvent(NULL,false,false,NULL);
p = waveOutOpen(
(LPHWAVEOUT)&sound_out_handle, // указатель на устройство воспроизведения
WAVE_MAPPER, // идентификатор открываемого устройства (WAVE_MAPPER по умолчанию)
(LPWAVEFORMATEX)&wfx.wFormatTag, // указатель на структуру WAVEFORMATEX с описанием формата звук данных
(DWORD)hEvent, // адрес функции обратного вызова
NULL, // доп произвольный параметр для функции обратного вызова
CALLBACK_EVENT); // флаг для открытия устройства
t->Resume();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
t->Terminate();
// завершение работы с аудиоустройством
waveOutReset(sound_out_handle);
waveOutUnprepareHeader (sound_out_handle, &hdr, sizeof(hdr));
waveOutClose(sound_out_handle);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormClose(TObject *Sender, TCloseAction &Action)
{
//И освобождаем наш объект-событие.
CloseHandle(hEvent);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
amp = StrToInt(Edit1->Text);
}
//---------------------------------------------------------------------------
Модуль потока
//---------------------------------------------------------------------------
#include
#pragma hdrstop
#include "Unit2.h"
#include "Unit1.h"
#include
#include
#pragma package(smart_init)
#define max 40000
extern WAVEFORMATEX wfx; // структура формата данных
extern HWAVEOUT sound_out_handle; // описатель устройства вывода
extern WAVEHDR hdr; // спец структура
extern HANDLE hEvent;
int i,j,l;
double k;
short int buff[max];
extern int amp;
//---------------------------------------------------------------------------
// Important: Methods and properties of objects in VCL can only be
// used in a method called using Synchronize, for example:
//
// Synchronize(UpdateCaption);
//
// where UpdateCaption could look like:
//
// void __fastcall TSound::UpdateCaption()
// {
// Form1->Caption = "Updated in a thread";
// }
//---------------------------------------------------------------------------
__fastcall TSound::TSound(bool CreateSuspended)
: TThread(CreateSuspended)
{
}
//---------------------------------------------------------------------------
void __fastcall TSound::Execute()
{
float OmegaC = 2*M_PI*400;
double t, tPred;
tPred = 0;
while (!Terminated)
{
// Отправка заголовка драйверу
waveOutWrite(
sound_out_handle, // идентификатор устройства воспроизведения
&hdr, // указатель на структуру wavehdr_tag сформированную с помощью waveOutPrepareHeader
sizeof(WAVEHDR)); // размер структуры wavehdr_tag
WaitForSingleObject(hEvent, INFINITE);
//waveOutUnprepareHeader (sound_out_handle, &hdr, sizeof(hdr));
for (i=0;i
{
buff
= amp*sin(OmegaC*i/8000);
}
// Указатель на звуковые данные
hdr.lpData = (char* )buff;
// Описание заголовка
hdr.dwFlags = 0;
// Свободное для записи поле
hdr.dwUser = 0;
// Размер звуковых данных
hdr.dwBufferLength = max*2;
// Количество записанных байт
hdr.dwBytesRecorded = 0;
// Количество повторов воспроизведения звуковых данных
hdr.dwLoops = 0;
// Подготовка заголовков для отправки драйверу
waveOutPrepareHeader(
sound_out_handle, // идентификатор устройства воспроизведения
&hdr, // указатель на структуру wavehdr_tag
sizeof(WAVEHDR)); // размер структуры wavehdr_tag
}
}
//---------------------------------------------------------------------------
Записан
OVE
Участник
Сказали спасибо: +67/-0
Offline
Сообщений: 72
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #1 :
11 Январь 2014, 11:37:57 »
Подозреваю, что нужно
Код:
for (i=0;i
{
buff[i] = amp*sin(OmegaC*i/8000);
}
И параметр max нужно выбрать так, чтобы не было скачков по фазе между двумя смежными синусоидами
Записан
Sergey1985
Участник
Сказали спасибо: +8/-1
Offline
Сообщений: 310
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #2 :
11 Январь 2014, 14:15:38 »
И вот еще вопросик. Для работы с двумя каналами надо генерировать звуковые данные для каждого канала отдельно а потом их смешивать. Вопрос как это понять СМЕШИВАТЬ? Ну вот с точки зрения математики. Каждую пару последовательных семплом с разных каналов друг с другом складывать или что? Читал статью ЕЩЕ РАЗ О ЗВУКЕ в Королевстве Делфи так там эта функция Mix на асме приведена. В общем мало что понятно.
Записан
Hex
Участник
Сказали спасибо: +16/-3
Offline
Сообщений: 38
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #3 :
11 Январь 2014, 23:05:35 »
в качестве примера видимо брали что то типа
http://www.delphisources.ru/pages/faq/base/about_sound_again.html ?
а зря, пример кривой и с ошибками. причем перепечатывается разными идиотами с завидной регулярностью.
Немного теории воспроизведения звука:
выводимый звук - это непрерывний сигнал, соотв, программа должна эту непрерывность обеспечить.
когда программа ставит буфер на воспроизведение, система добавляет его в очередь и передает драйверу вывода
пока самый первый поставленный в очередь блок воспроизводится, в очередь системы можно добавить еще несколько буферов на вывод,
при этом пауз между блоками не будет и выводимые данные будут звучать нормально без пауз и щелчков.
В вашей проге алгоритм кривоват:
1. передача блока на вывод
2. ожидание завершения вывода
3. подготовка нового блока (в этот момент могут возникать разные шумы, т.к. система завершила вывод и имеет право откл канал или еще чего там драйверу на ум придет)
4. заново
Как надо:
Выводим звук в режиме "двойной буферизации"
1. готовим 2 (4, 6, 8, 16, 32 - чем больше тем лучше, но в пределах разумного) буферов для вывода
2. заполняем ВСЕ блоки данными на вывод
3. передаем ВСЕ блоки на вывод (waveOutWrite())
4. следим за первым переданным блоком (index = 0)
5. если он полностью выведен, заполняем новыми данными и снова передаем на вывод
(в данный момент данные, переданные ранее все еще ждут вывода, новый блок ставится системой в хвост очереди на воспроизведение)
6. следим за вторым переданным блоком (index = 1)
7. и т.д. - индекс блока, за которым следим, начинает бегать по кругу (по числу буферов).
Насчет "смешивания" - выводите моно или стерео?
для стерео просто раскладываете звук по разным каналам ничего с ним не делая
а для моно да, достаточно суммировать семплы каналов (ну, если только вам не нужна какая то хитрая спец обработка)
Надеюсь доступно объяснил
PS и блин начинаем уже пользоваться тегами форума, а? хотя бы "code", а то исходник наполовину поеден
«
Последнее редактирование: 11 Январь 2014, 23:12:18 от Hex
»
Записан
Sergey1985
Участник
Сказали спасибо: +8/-1
Offline
Сообщений: 310
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #4 :
12 Январь 2014, 12:30:54 »
Да да именно это ссылка вернее не ссылка а сам код. Пробую естественно выводить в стерео. По одному каналу должна быть синусоида по второму косинус. (Хочу имитировать СКТ датчик) (СКТ - синусно-косинусный трансформатор)
Записан
Sergey1985
Участник
Сказали спасибо: +8/-1
Offline
Сообщений: 310
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #5 :
13 Январь 2014, 11:47:38 »
То есть для стерео просто раскладываете звук по разным каналам ничего с ним не делая? Это как? Разве есть где то переменная которая определяет номер канала? nChannels в WAVEFORMATEX это просто количество каналов но не определение самого канала левый или правый. Ничего не понимаю
Записан
Hex
Участник
Сказали спасибо: +16/-3
Offline
Сообщений: 38
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #6 :
13 Январь 2014, 11:57:54 »
буфер, передаваемый на вывод, содержит (для стерео сигнала) набор пар отсчетов: левый, правый, левый, правый, ...
подробно: http://microsin.net/programming/PC/wav-format.html
см. описание секции DATA
Записан
Sergey1985
Участник
Сказали спасибо: +8/-1
Offline
Сообщений: 310
Re: Как избавиться от пауз в генераторе НЧ
«
Ответ #7 :
13 Январь 2014, 12:52:20 »
Спасибо друг выручил
Записан
Страниц: [
1
]
Вверх
Печать
Перейти в:
Пожалуйста, выберите назначение:
-----------------------------
Вопросы программирования
-----------------------------
=> Общие вопросы программирования в C++Builder
=> Программирование с FMX
=> Работа с базами данных в C++Builder
=> Windows API
=> Технологии COM/DCOM, ActiveX
=> Аспекты и идеология профессиональной разработки ПО
=> Компьютерное железо и системное администрирование
=> студенческий городок
-----------------------------
Обсуждение материалов на сайте
-----------------------------
=> Обсуждений статей на сайте
=> Обсуждение материалов из файлового архива
=> Компоненты сторонних разработчиков к С++Builder
-----------------------------
Работа сайта и новости
-----------------------------
=> Ищу/предлагаю работу
=> Новости из мира программирования
=> Новости - события календаря
=> Голосования
=> Компьютерный юмор и приколы
=> Работа сайта
=> Флейм
-----------------------------
FAQ - частозадаваемые вопросы/ответы
-----------------------------
=> FAQ, общие вопросы, посвящённые C++Builder
=> FAQ, вопросы по базам данных
=> FAQ, вопросы по компонентам
Загружается...