Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Media";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];

Вниз

Тоновый набор   Найти похожие ветки 

 
Jee   (2003-07-30 15:05) [0]

Всем добрый день! Подскажите пожалуйста как выдать в колонку двухтональный сигнал. Хочу сделать, как было в аське 2000: поднес микрофон телефона к колонке и набрал номер.


 
Jee   (2003-07-30 15:17) [1]

Поставлю вопрос проще, есть функции, выводящие заданную частоту на колонку? Не на спикер. Или кроме wav винда ни с чем дела не имеет?


 
pasha676   (2003-07-30 15:24) [2]


> Или кроме wav винда ни с чем дела не имеет?

А все остальные форматы по твоему не поддерживаются ?

Что подразумевается под двухтональным сигналом? В WinNT и подобных тональный сигнал делается Beep. В 95 и их подобным придеться ручками делать.


 
Jee   (2003-07-30 15:30) [3]

В функция API я нашел BEEP, который выдает заданную частоту на спикер, что не подходит. Функцию MessageBee, которая выдает на колонки звук из предопределенных файлов wav. И последнее, функцию PlaySound, которая опять таки имет дело с wav. Отсюда мой вопрос.


 
pasha676   (2003-07-30 16:24) [4]

В 95 вроде на бластер она выдает. Если бластер есть, конечно.
В NT не знаю. Попробуй посмотреть API на саунды. Может там и есть. Их там много.


 
Jee   (2003-07-30 18:08) [5]

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


 
wiz   (2003-07-31 02:45) [6]

Если хочешь все сделать честно, лучше всего разобраться с работой WaveIn/WaveOut через WinAPI и вообще модулем mmsystem.

(в SDK ищем):

WaveOutOpen()
WaveOutPrepareHeader()
WaveOutWrite()
WaveOutReset()


Этих четырех хватит, чтобы организовать вывод звука.

Плюс структуры:

:TWaveFormatEX;
:HWaveout;
:TWaveHdr;


Плюс сообщение:
procedure OutWaveDone(Var msg:TMessage);Message MM_WOM_DONE; (Для отслеживания окончания проигрывания)

---

Попробуй разобраться... если что пойдет не так - пиши, я набью развернутый ответ с примером (Просто местное время 5:42 и уже жутко не хочется тыкать эти кнопки ;).


 
Jee   (2003-07-31 10:05) [7]

Если не трудно, кинь пожалуйста пример проигрывания какого-нибудь WAVа этими функциями.


 
wiz   (2003-08-01 00:24) [8]

Пример использования WinAPI функций из модуля mmsystem для организации вывода звука.

------------------------------------------------
interface

uses mmsystem;

const
OutbflenMax_c=44100;
BufLenght:integer = 40; //длина одного звукового буфера в мсек

type
TOutBuf = array[1..OutbflenMax_c] of smallint;

var
frm_handle:integer;

BufferSize:integer; // длина буфера в байтах

OutDev:HWaveout; // handle wave-девайса
OutdevFormat:TWaveFormatEX; // Описание формата вывода

OutWavehdr1:TWaveHdr; // header звукового буфера N1
OutWavehdr2:TWaveHdr; // header звукового буфера N2

Outbuf1:TOutBuf; // собственно буфер N1
Outbuf2:TOutBuf; // собственно буфер N2

outbfrnum:integer = 0; // номер буфера, который сейчас играет

//
// Процедура init"а звукового потока
procedure OutWaveInit;

//
// Процедура остановки звукового потока
procedure OutWaveThStop;

//
// Постановка очередного буфера на проигрывание
procedure OutWaveThRun;

//
// СГП (Самая! Главная! Процедура!).
// Здесь заполняют звуковой буфер всякой гадостью
procedure fill_buffer(header: pWaveHdr);

implementation

procedure OutWaveInit;
var
result:integer;
begin

//
// Вначале определим формат в котором должна работать звуковушка
//

with OutdevFormat do
Begin
wFormatTag :=WAVE_FORMAT_PCM;
nChannels :=2;
nSamplesPerSec :=44100;
wBitsPerSample :=16;
nBlockAlign :=nChannels * wBitsPerSample div 8;
nAvgBytesPerSec :=nSamplesPerSec * nBlockAlign;

BufferSize:=round(BufLenght/1000*nSamplesPerSec)*nBlockAlign;
// заодно определим размер буфера в байтах
End;
//wFormatTag : Формат потока - PCM
//nChannels : Кол-во каналов 1(моно) или 2(стерео)
//nSamplesPerSec : Частота дискретизации (11025,22050,44100 и др.)
//wBitsPerSample : Кол-во бит на один отсчет в одном канале (8 или 16)
//nBlockAlign : Кол-во байтов в одном "полном" отсчете
// (кол-во каналов умножить на кол-во байтов в канале)
//nAvgBytesPerSec: Кол-во байтов в секунду

//
// Теперь отрываем устройство вывода звука.
//

Result:=WaveOutOpen( @OutDev, // указатель на handle wave-девайса
WAVE_MAPPER, // номер звуковушки или -1 (WAVE_MAPPER)
// WAVE_MAPPER: звуковушка, которую установил
// пользователь по дефолту в настройках винды
@OutDevFormat, // Описание требуемого формата
frm_handle, // handle окна, которое будет получать messages
0,
CALLBACK_WINDOW);// механизм уведомления - messages окну

if result<>0 then showmessage("что-то здесь не так...");

//
// Теперь можно и буфер завести для звука.
//

with OutWaveHdr1 do
begin
lpData := pChar (@OutBuf1); // указатель на буфер
dwBufferLength := BufferSize; // длина буфера
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP or WHDR_DONE;
// главное: WHDR_DONE иначе уведомления об окончании
// проигрывания не будут поступать

dwLoops := 1;
lpNext := nil;
reserved := 0;
end;

Result:=WaveOutPrepareHeader(OutDev,@OutWaveHdr1,sizeof(TWaveHdr));

if result<>0 then showmessage("что-то здесь не так...");

//
// Теперь заведем еще один буфер, тогда пока один играет,
// второй в нашем полном распоряжении...
//
with OutWaveHdr2 do
begin
lpData := pChar (@OutBuf2);
dwBufferLength := waveinconst.BufferSize;
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP or WHDR_DONE;
dwLoops := 1;
lpNext := nil;
reserved := 0;
end;

Result:=WaveOutPrepareHeader(OutDev,@OutWaveHdr2,sizeof(TWaveHdr));

if result<>0 then showmessage("что-то здесь не так...");

//
// Усё... устройство открыто, буферы подготовлены.
// если где-то result<>0 смотри в SDK описание функции (там и ошибки расписаны)
//
end;

procedure OutWaveThStop;
begin
WaveOutReset(OutDev);
//
// Здесь все просто, как штыковая лопата.
//
end;

procedure OutWaveThRun;
var
result:integer;
begin
result:=0;
//
// Меняем номер буфера на противоположный (0,1);
//
outbfrnum:=(1-outbfrnum);

//
// ( @OutWaveHdr1) [8] Пример использования WinAPI функций из модуля mmsystem для организации вывода звука.

------------------------------------------------
interface

uses mmsystem;

const
OutbflenMax_c=44100;
BufLenght:integer = 40; //длина одного звукового буфера в мсек

type
TOutBuf = array[1..OutbflenMax_c] of smallint;

var
frm_handle:integer;

BufferSize:integer; // длина буфера в байтах

OutDev:HWaveout; // handle wave-девайса
OutdevFormat:TWaveFormatEX; // Описание формата вывода

OutWavehdr1:TWaveHdr; // header звукового буфера N1
OutWavehdr2:TWaveHdr; // header звукового буфера N2

Outbuf1:TOutBuf; // собственно буфер N1
Outbuf2:TOutBuf; // собственно буфер N2

outbfrnum:integer = 0; // номер буфера, который сейчас играет

//
// Процедура init"а звукового потока
procedure OutWaveInit;

//
// Процедура остановки звукового потока
procedure OutWaveThStop;

//
// Постановка очередного буфера на проигрывание
procedure OutWaveThRun;

//
// СГП (Самая! Главная! Процедура!).
// Здесь заполняют звуковой буфер всякой гадостью
procedure fill_buffer(header: pWaveHdr);

implementation

procedure OutWaveInit;
var
result:integer;
begin

//
// Вначале определим формат в котором должна работать звуковушка
//

with OutdevFormat do
Begin
wFormatTag :=WAVE_FORMAT_PCM;
nChannels :=2;
nSamplesPerSec :=44100;
wBitsPerSample :=16;
nBlockAlign :=nChannels * wBitsPerSample div 8;
nAvgBytesPerSec :=nSamplesPerSec * nBlockAlign;

BufferSize:=round(BufLenght/1000*nSamplesPerSec)*nBlockAlign;
// заодно определим размер буфера в байтах
End;
//wFormatTag : Формат потока - PCM
//nChannels : Кол-во каналов 1(моно) или 2(стерео)
//nSamplesPerSec : Частота дискретизации (11025,22050,44100 и др.)
//wBitsPerSample : Кол-во бит на один отсчет в одном канале (8 или 16)
//nBlockAlign : Кол-во байтов в одном "полном" отсчете
// (кол-во каналов умножить на кол-во байтов в канале)
//nAvgBytesPerSec: Кол-во байтов в секунду

//
// Теперь отрываем устройство вывода звука.
//

Result:=WaveOutOpen( @OutDev, // указатель на handle wave-девайса
WAVE_MAPPER, // номер звуковушки или -1 (WAVE_MAPPER)
// WAVE_MAPPER: звуковушка, которую установил
// пользователь по дефолту в настройках винды
@OutDevFormat, // Описание требуемого формата
frm_handle, // handle окна, которое будет получать messages
0,
CALLBACK_WINDOW);// механизм уведомления - messages окну

if result<>0 then showmessage("что-то здесь не так...");

//
// Теперь можно и буфер завести для звука.
//

with OutWaveHdr1 do
begin
lpData := pChar (@OutBuf1); // указатель на буфер
dwBufferLength := BufferSize; // длина буфера
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP or WHDR_DONE;
// главное: WHDR_DONE иначе уведомления об окончании
// проигрывания не будут поступать

dwLoops := 1;
lpNext := nil;
reserved := 0;
end;

Result:=WaveOutPrepareHeader(OutDev,@OutWaveHdr1,sizeof(TWaveHdr));

if result<>0 then showmessage("что-то здесь не так...");

//
// Теперь заведем еще один буфер, тогда пока один играет,
// второй в нашем полном распоряжении...
//
with OutWaveHdr2 do
begin
lpData := pChar (@OutBuf2);
dwBufferLength := waveinconst.BufferSize;
dwBytesRecorded := 0;
dwUser := 0;
dwFlags := WHDR_BEGINLOOP or WHDR_ENDLOOP or WHDR_DONE;
dwLoops := 1;
lpNext := nil;
reserved := 0;
end;

Result:=WaveOutPrepareHeader(OutDev,@OutWaveHdr2,sizeof(TWaveHdr));

if result<>0 then showmessage("что-то здесь не так...");

//
// Усё... устройство открыто, буферы подготовлены.
// если где-то result<>0 смотри в SDK описание функции (там и ошибки расписаны)
//
end;

procedure OutWaveThStop;
begin
WaveOutReset(OutDev);
//
// Здесь все просто, как штыковая лопата.
//
end;

procedure OutWaveThRun;
var
result:integer;
begin
result:=0;
//
// Меняем номер буфера на противоположный (0,1);
//
outbfrnum:=(1-outbfrnum);

//
// Теперь в нужный буфер заливаем данныt с помощью fill_buffer и добавляем в
// очередь на проигрывание
//
if outbfrnum = 0 then
begin
fill_buffer(@OutWaveHdr1);
Result:=WaveOutWrite(OutDev,@OutWaveHdr1,sizeof(TWaveHdr));
end
else
begin
fill_buffer(@OutWaveHdr2);
Result:=WaveOutWrite(OutDev,@OutWaveHdr2,sizeof(TWaveHdr));
end;


if result<>0 then showmessage("что-то здесь не так...");
end;

--- Конец стороны "А" ---


 
wiz   (2003-08-01 00:25) [9]

--- Сторона "Б" ---
var
time_from_begin:integer =0;
//
// Время от начала звучания (нам нужно, чтобы от буфера к буферу не рвалась
// фаза выводимой синусоиды)
//

procedure fill_buffer(header: pWaveHdr);
var
ptr:pointer;
p_outbuf:^TOutBuf;

a1,f1,w:double;

begin
ptr:=POutBuf(header.lpData);
p_outbuf:=ptr;

bflen:=waveinconst.BufferSamples;
sps:=waveinconst.SamplesPerSec;

//
// Для простоты будем выводить синус монохромат частотой 140 Гц
// в четверть громкости.
//

a1:=8192;
f1:=140;

w:=2*pi*f1/sps;

i:=1;
for u:=1 to bflen do
begin
p_outbuf^[i]:=round(a1*sin(time_from_begin*w));;
Inc(i);
p_outbuf^[i]:=round(a1*sin(time_from_begin*w));;
Inc(i);
inc(time_from_begin);
end;

end;

-----------------------------------------------------------------
Теперь в форме, которая будет принимать мессаги, об окончании буфера добавить
следующий обработчик:

type
TForm1 = class(TForm)
...
public
{ Public declarations }
procedure OutWaveDone(Var msg:TMessage);Message MM_WOM_DONE;
end;

var
Form1: TForm1;

...

implementation

...

procedure TForm1.OutWaveDone(Var msg:TMessage);
begin
OutWaveThRun;
end;

-------------------------------------------------------------------------
Init звука производим следующим образом:

---
OutWaveThInit;
OutWaveThRun;
OutWaveThRun;
---

2 (Два) "OutWaveThRun;" это не очепятка!!!

После выполнения такого кода в очереди проигрывания у драйвера звуковушки
окажется 2 буфера. По прошествии некоторого (BufLenght) времени первый буфер
доиграет и !!!БЕЗ ПАУЗЫ!!! начнет играть второй, а в это время винда сформирует
сообщение об окончании проигрывания, программа его примет, подготовит новый буфер
и поставит его в очередь. Та же история повторится со 2-ым, 3-ьм итд буфером.

Что будет если сделать очередь только из одного буфера???
Появится маленькая задержка между окончанием звучания одного буфера и
началом звучания другого. Хорошо, если выходные конденсаторы звуковой карты
сгладят эту паузу (правда такое бывает редко), или плохо, если появится хорошо
слышимый "щелчок" (А слушать щелчки каждые BufLenght миллисекунд довольно
напряжно).

---------------------------------------------------------

В: Что делать если я открыл канал, отыграл 3 секунды и теперь буду молчать 20 секунд?

О: Конечно, можно прибить вывод, а через 20 секунд создать снова. Но я рекомендую
все же оставить вывод, но забивать выходной буфер ноликами. Причина? Проста:
При открытии звукового потока WaveOutOpen винда задумывается. То есть выполнение
(с точки зрения программы) функции проходит очень быстро, но на самом деле
( Вместо PS: Оно хоть компилируется? Просто, нет под рукой Delphi,
чтобы проверить на ошибки/очепятки
) [9] --- Сторона "Б" ---
var
time_from_begin:integer =0;
//
// Время от начала звучания (нам нужно, чтобы от буфера к буферу не рвалась
// фаза выводимой синусоиды)
//

procedure fill_buffer(header: pWaveHdr);
var
ptr:pointer;
p_outbuf:^TOutBuf;

a1,f1,w:double;

begin
ptr:=POutBuf(header.lpData);
p_outbuf:=ptr;

bflen:=waveinconst.BufferSamples;
sps:=waveinconst.SamplesPerSec;

//
// Для простоты будем выводить синус монохромат частотой 140 Гц
// в четверть громкости.
//

a1:=8192;
f1:=140;

w:=2*pi*f1/sps;

i:=1;
for u:=1 to bflen do
begin
p_outbuf^[i]:=round(a1*sin(time_from_begin*w));;
Inc(i);
p_outbuf^[i]:=round(a1*sin(time_from_begin*w));;
Inc(i);
inc(time_from_begin);
end;

end;

-----------------------------------------------------------------
Теперь в форме, которая будет принимать мессаги, об окончании буфера добавить
следующий обработчик:

type
TForm1 = class(TForm)
...
public
{ Public declarations }
procedure OutWaveDone(Var msg:TMessage);Message MM_WOM_DONE;
end;

var
Form1: TForm1;

...

implementation

...

procedure TForm1.OutWaveDone(Var msg:TMessage);
begin
OutWaveThRun;
end;

-------------------------------------------------------------------------
Init звука производим следующим образом:

---
OutWaveThInit;
OutWaveThRun;
OutWaveThRun;
---

2 (Два) "OutWaveThRun;" это не очепятка!!!

После выполнения такого кода в очереди проигрывания у драйвера звуковушки
окажется 2 буфера. По прошествии некоторого (BufLenght) времени первый буфер
доиграет и !!!БЕЗ ПАУЗЫ!!! начнет играть второй, а в это время винда сформирует
сообщение об окончании проигрывания, программа его примет, подготовит новый буфер
и поставит его в очередь. Та же история повторится со 2-ым, 3-ьм итд буфером.

Что будет если сделать очередь только из одного буфера???
Появится маленькая задержка между окончанием звучания одного буфера и
началом звучания другого. Хорошо, если выходные конденсаторы звуковой карты
сгладят эту паузу (правда такое бывает редко), или плохо, если появится хорошо
слышимый "щелчок" (А слушать щелчки каждые BufLenght миллисекунд довольно
напряжно).

---------------------------------------------------------

В: Что делать если я открыл канал, отыграл 3 секунды и теперь буду молчать 20 секунд?

О: Конечно, можно прибить вывод, а через 20 секунд создать снова. Но я рекомендую
все же оставить вывод, но забивать выходной буфер ноликами. Причина? Проста:
При открытии звукового потока WaveOutOpen винда задумывается. То есть выполнение
(с точки зрения программы) функции проходит очень быстро, но на самом деле
поток открывается со значительным запаздыванием.

---------------------------------------------------------

Уффф... Вроде для начала все. Вопросы/замечания?

(Вместо PS: Оно хоть компилируется? Просто, нет под рукой Delphi,
чтобы проверить на ошибки/очепятки)


 
Jee   (2003-08-01 14:27) [10]

Спасибо огромное! Примерчик помог очень. Там правда есть пару мелких огрехов, но в конце-концов все заработало. Вернее почти все: не перехватываестя сообщение после проигрывания буфера. Но мне это пока некритично.


 
--0--   (2003-10-15 13:35) [11]

>Jee © (30.07.03 15:30) [3]
>В функция API я нашел BEEP, который выдает заданную частоту на >спикер, что не подходит.

а помоему Beep выводит на колонки или это нетак?
мне нужно вывести звук на спикер в NT, непоможете


 
--0--   (2003-10-15 13:35) [12]

>Jee © (30.07.03 15:30) [3]
>В функция API я нашел BEEP, который выдает заданную частоту на >спикер, что не подходит.

а помоему Beep выводит на колонки или это нетак?
мне нужно вывести звук на спикер в NT, непоможете



Страницы: 1 вся ветка

Форум: "Media";
Текущий архив: 2004.02.17;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.53 MB
Время: 0.009 c
1-53475
korvet
2004-02-06 10:53
2004.02.17
D3 не принимает команду при компиляции


1-53539
Draught
2004-02-05 12:38
2004.02.17
Является ли текст датой???


14-53699
Gero
2004-01-29 23:16
2004.02.17
Цвета в интерфейсе Office XP


6-53669
vvv2002
2003-12-09 10:36
2004.02.17
Как подключиться к сети через прокси сервер через idftp ?


1-53509
electric
2004-02-05 18:37
2004.02.17
Я в run-time создаю компонент TCheckBox , а как после его создани





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский