C++Builder
  Начало   Форум   Помощь Войти Регистрация  
Страниц: [1]   Вниз
  Печать  
Автор Тема: Как избавиться от пауз в генераторе НЧ  (Прочитано 2747 раз)
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]   Вверх
  Печать  
 
Перейти в:  




....

Powered by SMF 1.1.21 | SMF © 2025, Simple Machines
Страница сгенерирована за 0.09 секунд. Запросов: 21.