Разработка синтезатора звука в среде визуального программирования Delphi. Программная реализация

  • Вид работы:
    Курсовая работа (т)
  • Предмет:
    Информационное обеспечение, программирование
  • Язык:
    Русский
    ,
    Формат файла:
    MS Word
    109,18 Кб
  • Опубликовано:
    2014-12-11
Вы можете узнать стоимость помощи в написании студенческой работы.
Помощь в написании работы, которую точно примут!

Разработка синтезатора звука в среде визуального программирования Delphi. Программная реализация

Министерство образования Республики Беларусь

Учреждение образования

«Гомельский государственный университет

имени Франциска Скорины»

Факультет математический

Кафедра вычислительной математики и программирования





Разработка синтезатора звука в среде визуального программирования Delphi. Программная реализация

Курсовой проект



Исполнитель:

студент группы ПO-32

Дубовик Т. С.

Научный руководитель:

к.т.н., доцент кафедры

Цурганова Л. А.



Гомель 2014

Введение

Звук - физическое явление, представляющее собой распространение в виде упругих волн механических колебаний в твёрдой, жидкой или газообразной среде. В узком смысле под звуком имеют в виду эти колебания, рассматриваемые по отношению к тому, как они воспринимаются органами чувств животных и человека.

Как и любая волна, звук характеризуется амплитудой и спектром частот. Обычно человек осознаёт колебания, передаваемые по воздуху, в диапазоне частот от 16-20 Гц до 15-20 кГц. Звук ниже диапазона слышимости человека называют инфразвуком; выше: до 1 ГГц, - ультразвуком, от 1 ГГц - гиперзвуком.

Восприятие посредством слуха создает акустическое пространство, центр которого в каждый данный момент находится там, где находится источник звука, - в отличие от визуального пространства, центром которого является каждый воспринимающий посредством зрения человек.

Среди слышимых звуков следует особо выделить фонетические, речевые звуки и фонемы (из которых состоит устная речь) и музыкальные звуки (из которых состоит музыка).

В своём проекте я подробно рассмотрю генерацию звуковых волн и создание собственного источника (генератора звука) с помощью средства разработки Delphi.

Целью данного курсового проекта является подробное ознакомление с принципами генерации звука и создание собственного генератора звука.

1. Основные сведения о генераторе звука

Источниками звука могут стать любые явления, вызывающие местное изменение давления или механическое напряжение. Широко распространены источники звука в виде колеблющихся твёрдых тел (например, диффузоры громкоговорителей и мембраны телефонов, струны и деки музыкальных инструментов; в ультразвуковом диапазоне частот - пластинки и стержни из пьезоэлектрических материалов или магнитострикционных материалов). Источниками звука могут служить и колебания ограниченных объёмов самой среды (например, в органных трубах, духовых музыкальных инструментах, свистках и т.п.).

Чистый звуковой тон представляет собой звуковую волну, подчиняющуюся синусоидальному закону:

у =,

где  - максимальная амплитуда синусоиды;

 - частота (=);

 - количество колебаний упругой среды в секунду ();

 - период;

 - время (параметрическая переменная).

Звук характеризуется частотой (f), обычно измеряемой в герцах, т.е. количеством колебаний в секунду, и амплитудой (у). Амплитуда звуковых колебаний определяет громкость звука.

Для монотонного звука (меандр.) характерно постоянство амплитуды во времени.

Затухающие звуковые колебания характеризуются уменьшением амплитуды с течением времени.

Человек воспринимает механические колебания частотой 20 Гц - 20 КГц (дети - до 30 КГц) как звуковые. Колебания с частотой менее 20 Гц называются инфразвуком, колебания с частотой более 20 КГц - ультразвуком. Для передачи разборчивой речи достаточен диапазон частот от 300 до 3000 Гц.

Если несколько чистых синусоидальных колебаний смешать, то вид колебания изменится - колебания станут несинусоидальными.

Особый случай, когда смешиваются не любые синусоидальные колебания, а строго определенные, частота которых отличается в два раза (гармоники).

Основная гармоника имеет частоту, и амплитуду а1; вторая гармоника - частоту f2 и амплитуду а2; третья гармоника соответственно f3 и a3.

Причем f1<f2<f3, а1>а2>а3,При бесконечном количестве таких гармоник образуется периодический сигнал, состоящий из прямоугольных импульсов.

На слух всякое отклонение от синусоиды приводит к изменению звучания. В IBM PC источником звуковых колебаний является динамик (PC Speaker), воспроизводящий частоты приблизительно от 2 до 8 КГц. Для генерации звука в PC Speaker используются прямоугольные импульсы.


.1 Частотный синтез

Многоголосый частотный синтезатор предназначен для генерации звуковых сигналов сложной формы. Существуют два принципиально различных способа синтеза звуковых сигналов:

частотный синтез (FM - Fregueney Modulation);

волновой синтез (WS - Ware Synthesys).

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

Тембр звука формируется воздействием одной простой волны на другую с целью изменения ее частоты. Под воздейтсвием частотной модуляции возникают более спектрально богатые и сложные звуки, которые невозможно получить другими типами синтеза.

Впервые о применении частотной модуляции для синтеза звука задумался в 1966 году американец John Chowning , в будущем директор Центра компьютерных исследований музыки и акустики (CCRMA) Стенфордского университета, а на тот момент времени - преподаватель композиции кафедры электронной музыки.

В своём проекте я воспользовался методом генерации путём частотной модуляции, потому что он является достаточно эффективным и простым для реализации, к тому же спектр звуков, создаваемый с помощью частотной модуляции, действительно огромен.

2. Технология разработки генератора звука

Я разработал программу генератор звука в среде Borland Delphi с использованием стандартных классов TMemoryStream (для хранения звука в виде бинарных данных) и TStrings (для хранения характеристик конкретной частоты). Также описал новый класс TFreqObj и использовал достаточно нестандартный класс TWaveFormatEx для хранения формата аудиоданных.

При запуске пользователь может настроить громкость и частоту звука, также он должен выбрать качество звука и время проигрывания в миллисекундах (0 - зациклить). После нажатия кнопки “Старт” пользователь услышит синусоидальный звук соответствующей громкости и частоты.

Сейчас я подробно опишу используемые классы, а в дальнейшем подробно разберу процедуру MakeComplexSound.

.1 Класс TFreqObj

Я создал класс TFreqObj для удобства хранения и последующего использования характеристик частоты звука, таких, как:

 - максимальная амплитуда синусоиды;

 - частота (=);

 - количество колебаний упругой среды в секунду ().

Также в нём описан простейший конструктор с параметрами и функция приведения всех параметров в одну форматированную строку.

.2 Класс TWaveFormatEx

Для хранения информации об аудио-данных мы будем использовать класс TWaveFormatEx. Структура TWaveFormatEx определена следующим образом:

{wFormatTag;nChannels;nSamplesPerSec;nAvgBytesPerSec;nBlockAlign;wBitsPerSample;

WORD cbSize;

} WAVEFORMATEX;

Описание полей следующее:указывает тип аудио-данных. Нас интересуют только несжатые аудио-данные (PCM), поэтому для нас нужно чтобы тут было значение 0x0001 (то есть 1).определяет количество каналов.определяет норму отбора в секунду. Обычно используется значение 44100 Гц.чаще всего определяет среднюю скорость передачи байтов в секунду.определяет выравнивание в байтах.определяет количество бит для выборки. Обычно равно 8 либо 16.определяет размер всей структуры WAVEFORMATEX. Что в итоге равняется 18 байтам.

3 Алгоритмы и программная реализация генератора звука

Суть метода генерации состоит в следующем: в текстовом виде хранятся характеристики конкретной частоты (длина волны, частота и т.д.)в формате TFreqObj, затем создаётся экземпляр класса TWaveFormatEx (он предназначен для приведения звуковой информации в понятный аудиоплате вид), этот класс заполняется информацией о звуке и затем в него добавляется сгенерированная в зависимости от характеристик конкретной частоты информация (грубо говоря, звук в виде бинарных данных) и отсылается функцией PlaySound на аудиоплату.

3.1 Процедура MakeComplexSound

Данная процедура заполняет формат аудиоданных TWaveFormatEx, затем его заполняет сначала необходимыми низкими частотами (они нужны для корректного воспроизведения звука), а затем данными в зависимости от выбранной пользователем частоты.

Заполнение формата TWaveFormatEx:WaveFormatEx do:= WAVE_FORMAT_PCM;:= Mono;:= SampleRate;:= $0008;:= (nChannels * wBitsPerSample) div 8;:= nSamplesPerSec * nBlockAlign; := 0;

end;

Заполнение объекта типа TMemoryStream для последующего его отправления в процедуру PlaySound:

MS[n] := TMemoryStream.Create;MS[n] do:= (Duration * SampleRate) div 1000;:= Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount;(RiffId[1], 4); // 'RIFF'(RiffCount, SizeOf(DWORD)); // file data size(WaveId[1], Length(WaveId)); // 'WAVE'(FmtId[1], Length(FmtId)); // 'fmt ':= SizeOf(TWaveFormatEx);(TempInt, SizeOf(DWORD)); // TWaveFormat data size(WaveFormatEx, SizeOf(TWaveFormatEx)); // WaveFormatEx record(DataId[1], Length(DataId)); // 'data'(DataCount, SizeOf(DWORD)); // sound data size:=TFreqObj(freqlist.objects[0]).ftemp;:=0;:=false;:=samplerate div 2;i := 0 to trunc(2/minfreq*samplerate) do:=0;j:=0 to freqlist.count-1 doTFreqObj(freqlist.objects[j])<>nil thenTFreqObj(freqlist.objects[j]) doftemp>sampdiv2 then freqerror:=true;:= 2 * Pi * Ftemp;:=p/pi;:=soundvalue+trunc(Volume*a/1000*sin(ph+i*w/SampleRate);;soundvalue>maxvalmaxval:=soundvalue;;i := 0 to DataCount - 1 do:=127;j:=0 to freqlist.count-1 doTFreqObj(freqlist.objects[j])<>nil thenTFreqObj(freqlist.objects[j]) doftemp< sampdiv2 then:=samplerate/Ftemp;j=0 then setlength(imagedata,min(datacount,trunc(5*ptspercycle)));:=frac(i/ptspercycle+p/360);:=a/1000 ;:= 2 * Pi * Ftemp;:=p/pi;:=soundvalue+trunc(Volume*amp*sin(ph+i*w / SampleRate));;;maxval>127 then byteval:=soundvalue*127 div maxvalbyteval:=soundvalue;(Byteval, SizeOf(Byte));i<=high(imagedata) then imagedata[i]:=byteval;

end;;

3.2 Запись звука в файл

Получившийся звук можно записать в файл формата .WAV. Создавая поток для проигрывания нашей волны, мы уже задали в самом его начале формат данных, все характеристики нашей звуковой волны, то есть мы имеем заголовок и собственно звуковую волну в виде потока данных. Класс TMemoryStream, которым мы пользуемся для хранения потока в памяти, содержит метод SaveToFile. С помощью данного метода мы сохраняем наш поток в файл формата .WAV длиной в 1 секунду. Данный файл может быть воспроизведён в любом проигрывателе.

Ниже представлен код процедуры записи звука в файл:

procedure TForm1.Button1Click(Sender: TObject); программа генератор звукButton1.Caption='Запись в файл' then.Click;.Caption:='Сохранить';if Button1.Caption='Сохранить' then(nil,0,SND_Purge);:=false;SaveDialog2.Execute then[streaminuse].SaveToFile(SaveDialog2.FileName);.Caption:='Запись в файл';assigned (ms[streaminuse]) then freeandnil(Ms[streaminuse]);

end;;;

Заключение

В ходе выполнения курсового проекта были изучены основы программирования для работы со звуком: изучены основные понятия, некоторые классы для работы со звуком, а также использование потоков в создаваемом приложении. В качестве примера полученных навыков было разработано приложение “Генератор звука”.

Результат работы может использоваться на любом ПК для создания и изучения синусоидального звука.

Список использованных источников

Википедия - свободная энциклопедия // URL: https://www.wikipedia.org.ru - крупнейший ресурс в России о создании компьютерных игр // URL: https://www.gamedev.ru.ru - программирование звука в среде Windows // URL: https://www.soundcoding.ru

Кинтцель, Т. Руководство программиста по работе со звуком / Т. Кинтцель. - М.: ДМК, 2000. - 432 с.

Приложение А

Скриншот работы программы


Приложение Б

Исходный кодU_SoundGen2;, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,, mmsystem, StdCtrls, ComCtrls, Menus, CheckLst, ExtCtrls, shellAPI, Buttons;=class(TObject),f,P,a,shape:INTEGER;:String;Create(newf, newP, newA, newshape:integer);makestringrep;;= 0..127 ;= class(TForm): TPageControl;: TTabSheet;: TOpenDialog;: TSaveDialog;: TTabSheet;: TLabel;: TLabel;: TLabel;: TLabel;: TLabel;: TButton;: TButton;: TTrackBar;: TCheckListBox;: TTrackBar;: TRadioGroup;: TEdit;: TEdit;: TEdit;: TRadioGroup;: TUpDown;: TLabel;: TLabel;: TLabel;: TButton;: TSaveDialog;PlayBtnClick(Sender: TObject);StopBtnClick(Sender: TObject);VolBarChange(Sender: TObject);FormCreate(Sender: TObject);FreqbarChange(Sender: TObject);RateRgrpClick(Sender: TObject);VolEditChange(Sender: TObject);FreqEditChange(Sender: TObject);FreqEditKeyPress(Sender: TObject; var Key: Char);Button1Click(Sender: TObject);

{ Private declarations }

{ Public declarations }: array[0..1] of tmemorystream;:integer;:integer;, soundfilename :string;:TStringList;:boolean;:boolean;:boolean;:array of byte;MakeComplexSound(n:integer; freqlist:TStrings;{mSec}: Integer; Volume: TVolumeLevel);MsPlaySound;savesound;LoadSound(name:string);checkplaying;;: TForm1;: Integer = 11025; // 8000, 11025, 22050, or 44100

{$R *.DFM}math, U_SetFreq;makesoundname(name:string):string;n:integer;:string;:=extractfilename(name);:=pos('.',s);n>0 then delete(s,n,length(s)-n+1);:=s;;shapenames:array[0..3] of string=('Sine','Square','Sawtooth','Triangle');:string='DEFAULT.SND';TFreqObj.Create;create;:=newf;:=f;:=newp;:=newA;:=newSHAPE;;;TFreqObj.makestringrep;:=format('%5d (F:%4d, P:%4d, A:%4d %S)',[ftemp,f,p,a,SHAPENAMES[SHAPE]]);;: Word = $0001;: string = 'RIFF';: string = 'WAVE';: string = 'fmt ';: string = 'data';TForm1.MakeComplexSound(N:integer {stream # to use};:TStrings;{mSec}: Integer;: TVolumeLevel);: TWaveFormatEx;,j, TempInt, RiffCount: integer;: integer;:byte;, maxval:integer;,ph, amp: double;:boolean;:integer;:string;,x:extended;WaveFormatEx do:= WAVE_FORMAT_PCM;:= Mono;:= SampleRate;:= $0008;:= (nChannels * wBitsPerSample) div 8;:= nSamplesPerSec * nBlockAlign;:= 0;;[n] := TMemoryStream.Create;MS[n] do:= (Duration * SampleRate) div 1000;:= Length(WaveId) + Length(FmtId) + SizeOf(DWORD) +(TWaveFormatEx) + Length(DataId) + SizeOf(DWORD) + DataCount;(RiffId[1], 4); // 'RIFF'(RiffCount, SizeOf(DWORD)); // file data size(WaveId[1], Length(WaveId)); // 'WAVE'(FmtId[1], Length(FmtId)); // 'fmt ':= SizeOf(TWaveFormatEx);(TempInt, SizeOf(DWORD)); // TWaveFormat data size(WaveFormatEx, SizeOf(TWaveFormatEx)); // WaveFormatEx record(DataId[1], Length(DataId)); // 'data'(DataCount, SizeOf(DWORD)); // sound data size:=TFreqObj(freqlist.objects[0]).ftemp;:=0;:=false;:=samplerate div 2;i := 0 to trunc(2/minfreq*samplerate) do:=0;j:=0 to freqlist.count-1 doTFreqObj(freqlist.objects[j])<>nil thenTFreqObj(freqlist.objects[j]) doftemp>sampdiv2 then freqerror:=true;:= 2 * Pi * Ftemp;:=p/pi;:= soundvalue+ trunc(Volume * a/1000* sin(ph+i * w / SampleRate));;soundvalue>maxvalmaxval:=soundvalue;;i := 0 to DataCount - 1 do:=127;j:=0 to freqlist.count-1 doTFreqObj(freqlist.objects[j])<>nil thenTFreqObj(freqlist.objects[j]) doftemp< sampdiv2 then:=samplerate/Ftemp;j=0 then setlength(imagedata,min(datacount,trunc(5*ptspercycle)));:=frac(i/ptspercycle+p/360);:=a/1000 ;:= 2 * Pi * Ftemp;:=p/pi;:= soundvalue+ trunc(Volume * amp* sin(ph+i * w / SampleRate));;;maxval>127 then byteval:=soundvalue*127 div maxvalbyteval:=soundvalue;(Byteval, SizeOf(Byte));i<=high(imagedata) then imagedata[i]:=byteval;;;;TForm1.msPlaySound;options:integer;:=SND_MEMORY or SND_ASYNC;duration.position=0 then options:=options or SND_LOOP;(MS[streaminuse].Memory, 0, options);;TForm1.PlayBtnClick(Sender: TObject);:integer;:TStringlist;:integer;:integer;:=TStringlist.create;listbox1 doitems.count>0 theni:=0 to items.count-1 do if checked[i]freqlist.addobject(items[i],items.objects[i]);:=(streaminuse+1) mod 2;freqlist.count>0 then:=duration.position;unitsgrp.itemindex=1 then dur:=dur*1000;dur=0 then dur:=5000;(nextstream, freqlist, dur, Volbar.position);(sender);:=true;:=nextstream;;stopbtnclick(sender);.free;;;TForm1.StopBtnClick(Sender: TObject);(nil,0,SND_Purge);assigned (ms[streaminuse]) then freeandnil(Ms[streaminuse]);:=false;;TForm1.FormCreate(Sender: TObject);:=1;.activepage:=SoundSheet;('-Default.snd');;TForm1.CheckPlaying;playing then playbtnclick(self)(self);(self);;;TForm1.savesound;:textfile;:integer;(ff,soundfilename);(ff);(ff,'D',' ',duration.position,' ',unitsgrp.itemindex);i:=0 to listbox1.items.count-1 dolistbox1, TFreqObj(items.objects[i]) do writeln(ff,(checked[i]),' ', f,' ',p,' ',a,' ',shape,' ',stringrep);(ff);:=false;;TForm1.Loadsound(name:string);:textfile;:TFreqobj;:integer;:char;,units:integer;:=name;(ff,soundfilename);(ff);(ff,d);d='D' then(ff,dur, units);.position:=dur;.itemindex:=units;reset(ff);:=makesoundname(soundfilename);.clear;not eof(ff) dolistbox1 do:=tfreqobj.create(0,0,0,0);t do readln(ff,chk, f,p,a,shape,stringrep);.ftemp:=t.f;.AddObject(t.stringrep,t);[items.count-1]:=chk<>0;(ff);:=false;.position:=TFreqobj(listbox1.items.objects[0]).f;.position:=64;(self);;TForm1.FreqbarChange(Sender: TObject);:extended;:integer;freqbar.position>0 thenlistbox1,items docount>=1 then:=freqbar.position/TFreqobj(objects[0]).f;.text:=inttostr(freqbar.position);i:=0 to count-1 doobjects[i]<>nil thenTFreqObj(objects[i]) do:=round(f*scale);;[i]:=stringrep;;;;;;samprates:array[0..3] of integer=(8000,11025,22050,44100);TForm1.RateRgrpClick(Sender: TObject);:=samprates[rateRgrp.itemindex];;;TForm1.VolBarChange(Sender: TObject);.text:=inttostr(Volbar.position);;;TForm1.VolEditChange(Sender: TObject);n:integer;:=volbar.position;.position:=strtointdef(VolEdit.text,n);n<>volbar.position then volbarchange(sender);;TForm1.FreqEditChange(Sender: TObject);n:integer;:=freqbar.position;.position:=strtointdef(freqedit.text,n);n<>freqbar.position then FreqBarchange(sender);;TForm1.FreqEditKeyPress(Sender: TObject; var Key: Char);key=#13 then Freqeditchange(sender);;TForm1.Button1Click(Sender: TObject);Button1.Caption='Запись в файл' then.Click;.Caption:='Сохранить';if Button1.Caption='Сохранить' then(nil,0,SND_Purge);:=false;SaveDialog2.Execute then[streaminuse].SaveToFile(SaveDialog2.FileName);.Caption:='Запись в файл';assigned (ms[streaminuse]) then freeandnil(Ms[streaminuse]);

end;;;.

Похожие работы на - Разработка синтезатора звука в среде визуального программирования Delphi. Программная реализация

 

Не нашли материал для своей работы?
Поможем написать уникальную работу
Без плагиата!