Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 11.05.2012, 21:39   #1
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию проблема с выводом звука определенной частоты в короткие промежутки времени.

Ребят такая проблема.. нужно вывести на колонки звуковые отрывки частотой к примеру 1000Hz длительностью 30-100 МСек и между звуками паузу такой же длительности. Не могу найти достаточно быстрый способ для этого (дело в том, что на слабеньких компьютерах (либо на загруженных процессами) иногда идет залипание звучания). Пока что самого более менее подходящего звучания добился с помощью компонента TGen, причем только при установке Duration(длительности звучания) и команды Gen1.Play (Без Gen1.Stop) а между звуками и на время звучания TGen(так как синтез звука идет потоком) использовал наиболее точную (по тестам) паузу приведенную в коде
Код:
procedure Delay(MilliS: int64);
var
  Frq_Base, Time_memo, Time_now, dif: Int64;
begin
  MilliS:=MilliS*1000;
  if QueryPerformanceFrequency(Frq_Base) then // Частота ПК
    begin
      QueryPerformanceCounter(Time_memo);        // начальное значение
      repeat
      QueryPerformanceCounter(Time_now);
      dif := ((Time_now - Time_memo) * 1000000) div Frq_Base;
      until dif > MilliS;
    end;
end;
.
Есть какие нибудь предложения как ускорить этот процесс?
JekaDefer вне форума Ответить с цитированием
Старый 11.05.2012, 22:18   #2
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Первое впечатление - Вы подходите к генерации звука совершенно не с тех позиций, с которых принято, а потому Ваша программа требует себе 100% процессорного времени и не сможет нормально функционировать в многозадачной ОС.

Так что нужно не думать, как ускорить процесс, а почитать об основах синтеза звука на архитектуре IBM PC.
s-andriano вне форума Ответить с цитированием
Старый 11.05.2012, 22:47   #3
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию

ну в принципе другого ответа я и не ожидал) от подобных форумов всегда мало толку) спс за то что хоть отвечаете))
JekaDefer вне форума Ответить с цитированием
Старый 11.05.2012, 22:53   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

вам ответили верно.
лучше генерировать звук с запасом некоторым, а не на сейчас.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 11.05.2012, 23:19   #5
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

А чего Вы ждали, задавая вопрос и приводя в качестве примера фрагмент, который НЕ ГЕНЕРИРУЕТ звук?

А соображение, что Вы копаете не в ту сторону у меня появились оттого, что QueryPerformanceFrequency/QueryPerformanceCounter к генерации звука не относится и при такой генерации не используется. Если Вы пытаетесь его применить, то что-то делаете не так.

Если хотите получить совет, который хоть с какой-то вероятностью может оказаться полезным, расскажите подробнее, каким методом Вы генерируете звук.
s-andriano вне форума Ответить с цитированием
Старый 11.05.2012, 23:38   #6
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию

смысл в том чтоб вывести звуковой сигнал длительностью ровно 30 Мсек с минимальной погрешностью.

ну и еще одновременно отобразить за время пищания например картинку. а код который я привел это код наиболее точнейшей паузы если вы внимательно читали. Генерировал сигнал компонентом TGen
потому что подобные этому (
Код:
procedure MakeSound(Frequency{Hz}, Duration{mSec}: Integer; Volume: TVolumeLevel);
{writes tone to memory and plays it}
var
WaveFormatEx: TWaveFormatEx;
MS: TMemoryStream;
i, TempInt, DataCount, RiffCount: integer;
SoundValue: byte;
w: double; // omega ( 2 * pi * frequency)
const
Mono: Word = $0001;
SampleRate: Integer = 11025; // 8000, 11025, 22050, or 44100
RiffId: string = 'RIFF';
WaveId: string = 'WAVE';
FmtId: string = 'fmt ';
DataId: string = 'data';
begin
if Frequency > (0.6 * SampleRate) then
begin
   ShowMessage(Format('Sample rate of %d is too Low to play a tone of %dHz',
     [SampleRate, Frequency]));
   Exit;
end;
with WaveFormatEx do
begin
   wFormatTag := WAVE_FORMAT_PCM;
   nChannels := Mono;
   nSamplesPerSec := SampleRate;
   wBitsPerSample := $0008;
   nBlockAlign := (nChannels * wBitsPerSample) div 8;
   nAvgBytesPerSec := nSamplesPerSec * nBlockAlign;
   cbSize := 0;
end;
MS := TMemoryStream.Create;
with MS do
begin
   {Calculate length of sound data and of file data}
   DataCount := (Duration * SampleRate) div 1000; // sound data
   RiffCount := Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +
     SizeOf(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount; // file data
   {write out the wave header}
   Write(RiffId[1], 4); // 'RIFF'
   Write(RiffCount, SizeOf(DWORD)); // file data size
   Write(WaveId[1], Length(WaveId)); // 'WAVE'
   Write(FmtId[1], Length(FmtId)); // 'fmt '
   TempInt := SizeOf(TWaveFormatEx);
   Write(TempInt, SizeOf(DWORD)); // TWaveFormat data size
   Write(WaveFormatEx, SizeOf(TWaveFormatEx)); // WaveFormatEx record
   Write(DataId[1], Length(DataId)); // 'data'
   Write(DataCount, SizeOf(DWORD)); // sound data size
   {calculate and write out the tone signal} // now the data values
   w := 2 * Pi * Frequency; // omega
   for i := 0 to DataCount - 1 do
   begin
     SoundValue := 127 + trunc(Volume * sin(i * w / SampleRate)); // wt = w * i / SampleRate
     Write(SoundValue, SizeOf(Byte));
   end;
   {now play the sound}
   sndPlaySound(MS.Memory, SND_MEMORY or SND_SYNC);
   MS.Free;
end;
end;
коду с данной задачей совсем не справляются.

Меня интересует реально ли вообще такое сделать или не стоит мудрить?)
Вложения
Тип файла: zip gen.zip (8.5 Кб, 13 просмотров)

Последний раз редактировалось Stilet; 12.05.2012 в 08:10.
JekaDefer вне форума Ответить с цитированием
Старый 11.05.2012, 23:48   #7
veniside
Старожил
 
Регистрация: 03.01.2011
Сообщений: 2,508
По умолчанию

Вместо никому не нужной паузы, просто отсчитывайте число сэмплов. Например, для частоты оцифровки 44100Hz, 30 мс сигнала соответсвуют 1323 семплам. Вот их и посылайте на колонки. Будет ровно 30 мс звука со 100% точностью на любом процессоре.

> с данной задачей совсем не справляются.

Ну так вместо убитой sndPlaySound() надо пользоваться WaveOutOpen(), waveOutWrite() и далее по тексту.
"Когда приходит положенное время, человек перестаёт играть в пинбол. Только и всего."

Последний раз редактировалось veniside; 11.05.2012 в 23:55.
veniside вне форума Ответить с цитированием
Старый 12.05.2012, 07:46   #8
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Цитата:
Сообщение от JekaDefer Посмотреть сообщение
смысл в том чтоб вывести звуковой сигнал длительностью ровно 30 Мсек с минимальной погрешностью.
Цитата:
а код который я привел это код наиболее точнейшей паузы
Не нужно так делать паузы.
Паузы формируются непосредственно в звуковом буфере. Т.е. звуковой буфер состоит из участков с синусоидой (звук) и с прямой линией (пауза) и при этом непрерывно проигрывается.

Кстати, если Вам непременно нужна минимальная погрешность, лучше разрядность звука выбирать равной 16, а частоту дискретизации - повыше, например, 48000 Гц.
s-andriano вне форума Ответить с цитированием
Старый 12.05.2012, 20:24   #9
JekaDefer
Форумчанин
 
Регистрация: 07.04.2009
Сообщений: 112
По умолчанию

Цитата:
Сообщение от veniside Посмотреть сообщение
Вместо никому не нужной паузы, просто отсчитывайте число сэмплов. Например, для частоты оцифровки 44100Hz, 30 мс сигнала соответсвуют 1323 семплам. Вот их и посылайте на колонки. Будет ровно 30 мс звука со 100% точностью на любом процессоре.
Можешь пример привести где так вот с количеством сэмплов работать можно? А то чтото не получается у меня... Могу сделать только так - нажимаешь - играет.. нажимаешь на стоп - прекращает.. не соображу как с помощью количества сэмплов длительность внедрить. по этому то собственно и пользовался процедурой паузы.. Кстати если можно то вывод звука без использования потоков надо...

Последний раз редактировалось JekaDefer; 12.05.2012 в 20:28.
JekaDefer вне форума Ответить с цитированием
Старый 12.05.2012, 21:15   #10
s-andriano
Старожил
 
Аватар для s-andriano
 
Регистрация: 08.04.2012
Сообщений: 3,229
По умолчанию

Вывод звука с использованием потоков - это правильно, и не нужно этого бояться.
Нарисуйте, что хотите получить, на бумаге. Ну, например, в масштабе 1 мс = 5 см.
Тогда в 5 см у Вас будет укладываться 1 период синусоиды. А 30-мс фрагмент - 30 периодов, укладывающихся в 1.5 метра.
30 мс пауза - те же полтора метра, только не синусоиды, а прямой.
Собственно, Вам нужно этот "рисунок" поместить в буфер. Но сначала провести дискретизацию с частотой, скажем, 48 кГц. Т.е. 48 отсчетов на 1 мс. Другими словами, через интервалы 50/48 ~ 1 мм на бумаге.
Можете нарисовать эти точки. Надеюсь, после того, как Вы их нарисуете или, хотя бы, мысленно представите, будет гораздо проще понять, как формировать звуковой буфер.

Если использовать не 48, а, как Вы планировали, 11.025 кГц, то точки дискретизации нужно ставить примерно через 4.5 мм.

Последний раз редактировалось s-andriano; 12.05.2012 в 21:18.
s-andriano вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Проблема с выводом времени работы программы murzilka6002 Общие вопросы C/C++ 0 13.12.2011 23:17
Нужно разобраться с выводом текущего времени ExDeGarse Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 1 21.06.2011 15:52
проблема с выводом -=Andriushka=- Помощь студентам 0 13.04.2011 21:46
Программа для воспроизведения тонового звука через промежуток времени Vl-sn Помощь студентам 9 12.03.2010 20:27
Промежутки времени SatiriK(rus) SQL, базы данных 4 19.11.2008 00:37