Windows
Code: |
uses MMSystem;
function GetMasterMute( Mixer: hMixerObj; var Control: TMixerControl): MMResult; // Returns True on success var Line: TMixerLine; Controls: TMixerLineControls; begin ZeroMemory(@Line, SizeOf(Line)); Line.cbStruct := SizeOf(Line); Line.dwComponentType := MIXERLINE_COMPONENTTYPE_DST_SPEAKERS; Result := mixerGetLineInfo(Mixer, @Line, MIXER_GETLINEINFOF_COMPONENTTYPE); if Result = MMSYSERR_NOERROR then begin ZeroMemory(@Controls, SizeOf(Controls)); Controls.cbStruct := SizeOf(Controls); Controls.dwLineID := Line.dwLineID; Controls.cControls := 1; Controls.dwControlType := MIXERCONTROL_CONTROLTYPE_MUTE; Controls.cbmxctrl := SizeOf(Control); Controls.pamxctrl := @Control; Result := mixerGetLineControls(Mixer, @Controls, MIXER_GETLINECONTROLSF_ONEBYTYPE); end; end;
procedure SetMasterMuteValue( Mixer: hMixerObj; Value: Boolean); var MasterMute: TMixerControl; Details: TMixerControlDetails; BoolDetails: TMixerControlDetailsBoolean; Code: MMResult; begin Code := GetMasterMute(0, MasterMute); if Code = MMSYSERR_NOERROR then begin with Details do begin cbStruct := SizeOf(Details); dwControlID := MasterMute.dwControlID; cChannels := 1; cMultipleItems := 0; cbDetails := SizeOf(BoolDetails); paDetails := @BoolDetails; end; LongBool(BoolDetails.fValue) := Value; Code := mixerSetControlDetails(0, @Details, MIXER_SETCONTROLDETAILSF_VALUE); end; if Code <> MMSYSERR_NOERROR then raise Exception.CreateFmt('SetMasterMuteValue failure, '+ 'multimedia system error #%d', [Code]); end;
// Example:
procedure TForm1.Button1Click(Sender: TObject); begin SetMasterMuteValue(0, CheckBox1.Checked); // Mixer device #0 mute on/off end; |
Взято с сайта https://www.swissdelphicenter.ch/en/tipsindex.php
Code: |
procedure SetVolume(X: Word); var iErr : Integer; i: integer; a: TAuxCaps; begin for i := 0 to auxGetNumDevs do begin auxGetDevCaps(i,Addr(a),SizeOf(a)); If a.wTechnology = AUXCAPS_CDAUDIO Then break; end;
// Устанавливаем одинаковую громкость для левого и правого каналов. // VOLUME := LEFT*$10000 + RIGHT*1
iErr:=auxSetVolume(i,(X*$10001)); if (iErr‹›0) then ShowMessage('No audio devices are available!'); end;
function GetVolume: Word; var iErr : Integer; i: integer; a: TAuxCaps; vol: word; begin for i := 0 to auxGetNumDevs do begin auxGetDevCaps(i,Addr(a),SizeOf(a)); If a.wTechnology = AUXCAPS_CDAUDIO Then break; end; iErr:=auxGetVolume(i,addr(vol)); GetVolume := vol; if (iErr‹›0) then ShowMessage('No audio devices are available!'); end; |
Автор: Alec Bergamini
Совместимость: Delphi 5.x (или выше)
11-го августа 2001 Microsoft объявила о выпуске SAPI 5.1 SDK. Данный продукт можно использовать в любом языке, который поддерживает OLE автоматизацию.
В данной статье я постараюсь раасказать, как установить SAPI 5.1 SDK. Затем мы посмотрим, как использовать SDK в приложении Delphi для преобразования текста в синтезированную речь. Синтезированная речь будет проигрываться через спикер. Всё это тестировалось в Delphi 5 и 6.
Чтобы скачать SAPI 5.1, необходимо зайти на сайт Microsoft's Speech.net Technologies по адресу https://www.microsoft.com/speech/ и кликнуть по ссылке download. Далее будет предложено прочитать комментарии к данному продукту. Если в Вашей системе, язык по умолчанию отличается от US English, то настоятельно рекомендую прочитать эти комментарии до конца.
Если Вы используете beta версию операционной системы XP, то у Вас могут возникнуть некоторые проблемы. Проблемы связаны с тем, что большинство beta версий XP включают в себя ранние версии SAPI 5.1. Поэтому не пытайтесь инсталировать release версию SAPI 5.1 на XP, она не будет работать.
После того как Вы прочитаете комментарии, то приступайте к скачиванию Speech SDK 5.1. Всё что для этого потребуется, это нажать на ссылку Speech SDK 5.1 (68 MB). В архиве содержится сам SDK, докумантация, а так же текты на английском для примера.
Итак, после скачивания SAPI 5.1 SDK, запустите speechsdk51.exe для установки его на Ваш компьютер.
Теперь надо дать знать Delphi о новых объектах автоматизации SAPI. Для этого запустите Delphi 5 или 6 (Я не пробовал боле ранние версии) и откройте Project | Import Type Library. В диалоге Import Type Library выберите "Microsoft Speech Object Library (Version 5.1)". Если Вы не нашли его в списке, значит во время инсталяции SAPI 5.1 произошли какие-то ошибки.
Delphi предложит поместить компоненты SAPI на станицу ActiveX. Я рекомендую разместить их в новой странице под названием "SAPI 5", так как количество компонент довольно большое (19). Так же рекомендую Вам выбрать "Unit dir name" отличающуюся от той, которая предлагается по умолчанию. Убедитесь, что на "Generate Component Wrapper" стоит галочка и нажмите кнопку >Install<.
В диалоге Install выберите закладку "Into new package" и в поле "File name:" введите имя пакета наподобие "SAPI5.dpk", нажмите кнопку "Обзор..." (browse) и убедитесь, что dpk создан в той же директории, в которой были созданы компоненты. В диалоге Install в поле Description задайте какое-нибудь описание, например "SAPI 5 automation components". Нажмите OK
В подтверждающем диалоге нажмите yes. После этого новые компоненты будут установлены.
Теперь, если Вы посмотрите в директорию, которую указали для установки компонент, то обнаружите там файл SpeechLib_TLB.pas (и dcr) который содержит весь код компоненты (интерфайс, константы, типы, а так же другую полезную информацию). Эта директория так же содержит (если Вы следовали вышеприведённым инструкциям) SAPI5.dpk который является исходинком пакета.
А теперь самая интересная часть.
Давайте создадим приложение, которое будет синтезировать речь. В Delphi создайте новое приложение и поместите на форму кнопку. На странице компонент SAPI5 найдите SpVoice и перетащите его на форму.
Теперь создайте событие onClick для Вашей кнопки, которое должно выглядеть примерно так:
Code: |
procedure TForm1.Button1Click(Sender: TObject); begin SpVoice1.Speak('Hello world!', SVSFDefault); end; |
Запустите программу и нажмите кнопку. Здорово?
Метод Speak объекта SPVoice предоставляет довольно большие возможности. Эти возможности можно использовать если поиграться со вторым параметром. В вышеприведённом примере я использовал режим поумолчанию, который позволяет функции вернуть управление только после завершения проигрывания звука. Избежать этого можно путём внедрения в текст специальных тэгов XML.
Документация по SDK содержит файл sapi.chm который можно найти в директории \Program Files\Microsoft Speech SDK 5.1\Docs\Help .
Sapi.chm содержит довольно много информации. Вот основные, часто используемые возможности компоненты и, соответствующие им флаги, которые передаются во втором параметре:
• Воспроизведение текста находящегося в файле. (SVSFIsFilename)
• Асинхронный решим проигрывания звука. Позволяет функции вернуть управление немедленно, во время воспроизведения. (SVSFlagsAsync)
• Позволяет управлять воспроизведением через XML тэги (см. раздел под название "XML TTS Tutorial"). Тэги позволяют настроить тональность звучания, скорость воспроизведения и многое другое.( SVSFIsXML)
Одна из интересных вещей (не документирована) заключается в том, что можно озвучивать заголовок веб страницы путём установки флага в SVSFIsFilenam а имени файла в URL. Если Вы соединены с интернетом, попробуйте запустить следующую строчку:
SpVoice1.Speak('https://www.o2a.com', SVSFIsFilename);
Так же при помощи этого флага можно проигрывать wav файлы:
SpVoice1.Speak('C:\WINNT\MEDIA\Windows Logon Sound.wav', SVSFIsFilename);
На самом деле у этой SAPI намного больше возможностей, чем я здесь привёл. В следующий раз, мы подробнее рассмотрим другие возможности.
Взято из https://forum.sources.ru
Code: |
// Works on NT, 2k, XP, Win9x with SAPI SDK // reference & Further examples: See links below!
uses Comobj;
procedure TForm1.Button1Click(Sender: TObject); var voice: OLEVariant; begin voice := CreateOLEObject('SAPI.SpVoice'); voice.Speak('Hello World!', 0); end; |
Взято с сайта https://www.swissdelphicenter.ch/en/tipsindex.php
Единственное, что удалось найти это компонент на Дельфи (с исходным кодом) на https://www.torry.net/mixer.htm компонент называется Vumeter v.1.0. Я его не разбирал, но похоже что он опрашивает Audio Mixer Driver (или что-то подобное).
Автор: Vit (www.delphist.com, www.drkb.ru, www.unihighlighter.com, www.nevzorov.org)
Взято с Vingrad.ru https://forum.vingrad.ru
Я построил диаграмму так:
Назначил F:= TFileStream.Create(OpenDialog1.FileName, fmOpenRead );
Затем считал заголовок Wav- SampleCount, SamplesPerSec, BitsPerSample, Channeles.
Затем считал данные- GetMem(buf, SampleCount * Channeles * BitsPerSample);
Описал массив Volume- SetLength(Volume, SampleCount);
Затем - F.Read(buf^, SampleCount*2); F.Free;
Затем заполнил массив -
Code: |
buf16 := buf; for h := 0 to SampleCount - 1 do begin Volume[h] := abs(buf16^); inc(buf16); end; FreeMem(buf); |
Затем строил график(в экранных координатах) - по горизонтальной оси откладывал значения SampleCount, по вертикальной значения Volume[h].
График получается точно такой же как в SoundForge.
Единственно, я писал программу для конкретного случая - у меня файлы по 10 минут, моно, 11025 Гц., 16 бит. Так что программа у меня не универсальная. Но работает нормально. По времени: обработка файла и построение графика около 4 -5 секунд.
Автор ответа: TPavel
WaveOutSetVolume()
Code: |
{ ... } if WaveOutGetNumDevs > 0 then ShowMessage('Wave-Device present') else ShowMessage('No Wave-Device present'); { ... } |
Code: |
function IsSoundCardInstalled: Boolean; type SCFunc = function: UInt; stdcall; var LibInst: LongInt; EntryPoint: SCFunc; begin Result := False; LibInst := LoadLibrary(PChar('winmm.dll')); try if LibInst <> 0 then begin EntryPoint := GetProcAddress(LibInst, 'waveOutGetNumDevs'); if (EntryPoint <> 0) then Result := True; end; finally if (LibInst <> 0) then FreeLibrary(LibInst); end; end; |
Взято с Delphi Knowledge Base: https://www.baltsoft.com/
Code: |
unit receiver; interface uses mmsystem, classes; const samp_per_sec = 44100; samp_cnt = samp_per_sec div 5; buf_len = samp_cnt * 2; type PSample16M = ^TSample16M; TSample16M = SmallInt; PArrayOfSample = ^TArrayOfSample; TArrayOfSample = array[1..samp_cnt] of TSample16M; TReceiver = class private hwi: Integer; fmt: tWAVEFORMATEX; whdr1: WAVEHDR; buf1: TArrayOfSample; whdr2: WAVEHDR; buf2: TArrayOfSample; FStoped: Boolean; FOnChange: TNotifyEvent; procedure SetStoped(const Value: Boolean); public Peak: Integer; Buffer: PArrayOfSample; destructor Destroy; override; procedure Start; procedure Stop; property Stoped: Boolean read FStoped write SetStoped; property OnChange: TNotifyEvent read FOnChange write FOnChange; end; var rec: TReceiver;
implementation
procedure waveInProc(const hwi, uMsg, dwInstance: Integer; var hdr: WAVEHDR; const dwP2: Integer); stdcall; const divs = samp_cnt div 100; var i, p: Integer; buf: PArrayOfSample; begin if rec.Stoped then Exit; case uMsg of WIM_OPEN: begin end; WIM_DATA: begin rec.Buffer := PArrayOfSample(hdr.lpData); buf := PArrayOfSample(hdr.lpData); p := 0; for i := 0 to samp_cnt div divs do p := p + Abs(buf[i * divs]); rec.Peak := p div (samp_cnt div divs); if Assigned(rec.FOnChange) then rec.FOnChange(rec); waveInUnprepareHeader(hwi, @hdr, SizeOf(WAVEHDR)); waveInPrepareHeader(hwi, @hdr, SizeOf(WAVEHDR)); waveInAddBuffer(hwi, @hdr, SizeOf(WAVEHDR)); end; WIM_CLOSE: begin end; end; end;
{ TReceiver }
destructor TReceiver.Destroy; begin Stoped := True; inherited; end;
procedure TReceiver.SetStoped(const Value: Boolean); begin FStoped := Value; if Value then begin waveInStop(hwi); waveInUnprepareHeader(hwi, @whdr1, SizeOf(WAVEHDR)); waveInUnprepareHeader(hwi, @whdr2, SizeOf(WAVEHDR)); waveInReset(hwi); waveInClose(hwi); end else begin with fmt do begin wFormatTag := WAVE_FORMAT_PCM; nChannels := 1; nSamplesPerSec := samp_per_sec; nBlockAlign := 2; nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; wBitsPerSample := 16; cbSize := 0; end; waveInOpen(@hwi, WAVE_MAPPER, @fmt, Cardinal(@waveInProc), hInstance, CALLBACK_FUNCTION); with whdr1 do begin lpData := @buf1; dwBufferLength := buf_len; dwBytesRecorded := 0; dwUser := 0; dwFlags := 0; dwLoops := 0; lpNext := nil; reserved := 0; end; waveInPrepareHeader(hwi, @whdr1, SizeOf(WAVEHDR)); waveInAddBuffer(hwi, @whdr1, SizeOf(WAVEHDR)); with whdr2 do begin lpData := @buf2; dwBufferLength := buf_len; dwBytesRecorded := 0; dwUser := 0; dwFlags := 0; dwLoops := 0; lpNext := nil; reserved := 0; end; waveInPrepareHeader(hwi, @whdr2, SizeOf(WAVEHDR)); waveInAddBuffer(hwi, @whdr2, SizeOf(WAVEHDR)); waveInStart(hwi); end; end;
procedure TReceiver.Start; begin Stoped := False; end;
procedure TReceiver.Stop; begin Stoped := True; end;
initialization rec := TReceiver.Create; finalization rec.Free; end. |
вот. отображать уровень можно через поле Peak при событии OnChange, там же (в этом событии) можно работать с полем Buffer в котором как раз содержется записанный сигнал.
Вся работа осуществляется через глобальную переменную rec . Возможно это не лучшая реализация с точки зрения ООП, но работает Запись происходит с глубиной 16 бит и частотой 44100 в режиме моно. После небольшой переделки все это может работать с любыми частотами и каналами и глубинами.
Автор cully
Взято с Vingrad.ru https://forum.vingrad.ru
Code: |
procedure GetVolume(var volL, volR: Word); var hWO: HWAVEOUT; waveF: TWAVEFORMATEX; vol: DWORD; begin volL := 0; volR := 0; // init TWAVEFORMATEX FillChar(waveF, SizeOf(waveF), 0); // open WaveMapper = std output of playsound waveOutOpen(@hWO, WAVE_MAPPER, @waveF, 0, 0, 0); // get volume waveOutGetVolume(hWO, @vol); volL := vol and $FFFF; volR := vol shr 16; waveOutClose(hWO); end;
procedure SetVolume(const volL, volR: Word); var hWO: HWAVEOUT; waveF: TWAVEFORMATEX; vol: DWORD; begin // init TWAVEFORMATEX FillChar(waveF, SizeOf(waveF), 0); // open WaveMapper = std output of playsound waveOutOpen(@hWO, WAVE_MAPPER, @waveF, 0, 0, 0); vol := volL + volR shl 16; // set volume waveOutSetVolume(hWO, vol); waveOutClose(hWO); end; |
Взято с Delphi Knowledge Base: https://www.baltsoft.com/
пример взят из рассылки "Мастера DELPHI. Новости мира компонент, FAQ, статьи..."
Code: |
procedure TForm1.btRecordClick(Sender: TObject); begin with Media do begin { Set FileName to the test.wav file to } { get the recording parameters. } FileName := 'd:\test.wav'; { Open the device. } Open; { Start recording. } Wait := False; StartRecording; end; end;
procedure TForm1.btStopClick(Sender: TObject); begin with Media do begin { Stop recording. } Stop; { Change the filename to the new file we want to write. } FileName := 'd:\new.wav'; { Save and close the file. } Save; Close; end; end; |
Взято с Vingrad.ru https://forum.vingrad.ru
Эта программа увеличивает громкость выбранного канала на 1000.
Code: |
uses MMSystem;
procedure TForm1.Button1Click(Sender: TObject); var vol: longint; LVol, RVol: integer; begin AuxGetVolume(ListBox1.ItemIndex, @Vol); LVol := Vol shr 16; if LVol < MaxWord - 1000 then LVol := LVol + 1000 else LVol := MaxWord; RVol := (Vol shl 16) shr 16; if RVol < MaxWord - 1000 then RVol := RVol + 1000 else RVol := MaxWord; AuxSetVolume(ListBox1.ItemIndex, LVol shl 16 + RVol); end;
procedure TForm1.FormCreate(Sender: TObject); var i: integer; cap: TAuxCaps; begin for i := 0 to auxGetNumDevs - 1 do begin auxGetDevCaps(i, Addr(cap), SizeOf(cap)); ListBox1.Items.Add(cap.szPname) end; end; |
Второй вариант:
Code: |
uses mmsystem;
function GetWaveVolume: DWord; var Woc : TWAVEOUTCAPS; Volume : DWord; begin result:=0; if WaveOutGetDevCaps(WAVE_MAPPER, @Woc, sizeof(Woc)) = MMSYSERR_NOERROR then if Woc.dwSupport and WAVECAPS_VOLUME = WAVECAPS_VOLUME then begin WaveOutGetVolume(WAVE_MAPPER, @Volume); Result := Volume; end; end;
procedure SetWaveVolume(const AVolume: DWord); var Woc : TWAVEOUTCAPS; begin if WaveOutGetDevCaps(WAVE_MAPPER, @Woc, sizeof(Woc)) = MMSYSERR_NOERROR then if Woc.dwSupport and WAVECAPS_VOLUME = WAVECAPS_VOLUME then WaveOutSetVolume(WAVE_MAPPER, AVolume); end;
procedure TForm1.Button1Click(Sender: TObject); begin Beep; end;
procedure TForm1.Button2Click(Sender: TObject); var LeftVolume: Word; RightVolume: Word; begin LeftVolume := StrToInt(Edit1.Text); RightVolume := StrToInt(Edit2.Text); SetWaveVolume(MakeLong(LeftVolume, RightVolume)); end;
procedure TForm1.Button3Click(Sender: TObject); begin Caption := IntToStr(GetWaveVolume); end; |
Автор MMM
Страница 41 из 42