Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Воспроизведение конкретных нот


Автор: Denioz 5.6.2006, 16:30
Подскажите пожалуйста, как воспроизводить определенные ноты, например "до" первой октавы? 

Автор: Snowy 5.6.2006, 18:05
Код
uses MMSystem;

var
  hmidi: HMIDIOUT;

procedure TForm1.FormCreate(Sender: TObject);
begin
  midioutopen(@hmidi, MIDI_MAPPER, 0, 0, 0); // открыть MIDI MAPPER
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  midioutclose(hmidi); // Закрыть MIDI
end;

procedure TForm1.Button1MouseDown(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  midioutshortmsg(hmidi, $7f2290); // Сыграть ноту
end;

procedure TForm1.Button1MouseUp(Sender: TObject; Button: TMouseButton;
  Shift: TShiftState; X, Y: Integer);
begin
  midioutshortmsg(hmidi, $7f2280); // прекратить ноту
end;

Формат комманды:
$7F2290
Здесь:
7F - громкость от ($0 до $7F)
22 - инструмент (от $0 до $7F)
9 - играть ноту (8 - прекратить играть)
0 - канал, на котором играть ноту (от 0 до $F) 

Автор: Snowy 5.6.2006, 18:22
Это был пример на MIDI.

А вот пример из DRKB (wav):
Код

uses  
  MMSystem;  

type  
  TVolumeLevel = 0..127;  

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;  

// How to call the function:  

procedure TForm1.Button1Click(Sender: TObject);  
begin  
  MakeSound(1200, 1000, 60);  
end; 


А вот пример из FAQ (спикер): http://vingrad.ru/DELPHI-DLP-001513 

Автор: TP@MB@Y 10.8.2006, 21:51
Snowy,  спасибо за пример с миди!! Но у меня не получается 25 инструмент сыграть, т.е. его ноты. Как я понял там идут инструменты по порядку со своими нотами, т.е. до ре ми фа соль ля си (с полутонами) одного инструмента, потом второго и т.д.
Мне нужен например 25 инструмент. С хексами у меня плоховато( Как смещение организовать попроще? :-\

Автор: Snowy 10.8.2006, 22:00
Открой стандартный калькулятор Windows.
Переведи его в инженерный редим.
Набери число
Переставь галочку на HEX - получишь HEX число.
Проще никак, т.к. байты не бьются в десятичном представлении.

Автор: TP@MB@Y 10.8.2006, 22:13
я так уже пробовал smile
смотри: у меня 25 -ый инструмент. я делаю так - 24*12=288 = 120(hex) эээм, хорошо. подставляю туда и у меня звучит не тот инструмент :-/

Автор: Snowy 10.8.2006, 22:17
Инструментов только 7F. 120 - уже выходит за пределы.

Автор: TP@MB@Y 10.8.2006, 22:25
Snowy,  окей, тогда, как мне обратиться к ноте До 25 инструмента? :-\\\\ 

Автор: Snowy 10.8.2006, 22:47
А вот этого я не знаю.
Как я понимаю, инструмент выбирается на канал.
Нужно задать нужному каналу нужный инструмент.
По дефолту на канале сидит пианина.
Циферка 22 в примере - задаёт тональность на канале.
А вот как задать каналу инструмент, я не разобрался.
Шашёл только список инструментов:
Цитата

0 Acoustic grand piano 8 Celesta 16 Hammond organ  
1 Bright acoustic piano 9 Glockenspiel 17 Percussive organ  
2 Electric grand piano 10 Music box 18 Rock organ  
3 Honky-tonk piano 11 Vibraphone 19 Church organ  
4 Rhodes piano 12 Marimba 20 Reed organ  
5 Chorused piano 13 Xylophone 21 Accordion  
6 Harpsichord 14 Tubular bells 22 Harmonica  
7 Clavinet 15 Dulcimer 23 Tango accordion  
24 Acoustic guitar (nylon) 32 Acoustic bass 40 Violin  
25 Acoustic guitar (steel) 33 Electric bass (finger) 41 Viola  
26 Electric guitar (jazz) 34 Electric bass (pick) 42 Cello  
27 Electric guitar (clean) 35 Fretless bass 43 Contrabass  
28 Electric guitar (muted) 36 Slap bass 1 44 Tremolo strings  
29 Overdriven guitar 37 Slap bass 2 45 Pizzicato strings  
30 Distortion guitar 38 Synth bass 1 46 Orchestral harp  
31 Guitar harmonics 39 Synth bass 2 47 Timpani  
48 String ensemble 1 56 Trumpet 64 Soprano sax  
49 String ensemble 2 57 Trombone 65 Alto sax  
50 Synth. strings 1 58 Tuba 66 Tenor sax  
51 Synth. strings 2 59 Muted trumpet 67 Baritone sax  
52 Choir Aahs 60 French horn 68 Oboe  
53 Voice Oohs 61 Brass section 69 English horn  
54 Synth voice 62 Synth. brass 1 70 Bassoon  
55 Orchestra hit 63 Synth. brass 2 71 Clarinet  
72 Piccolo 80 Lead 1 (square) 88 Pad 1 (new age)  
73 Flute 81 Lead 2 (sawtooth) 89 Pad 2 (warm)  
74 Recorder 82 Lead 3 (calliope lead) 90 Pad 3 (polysynth)  
75 Pan flute 83 Lead 4 (chiff lead) 91 Pad 4 (choir)  
76 Bottle blow 84 Lead 5 (charang) 92 Pad 5 (bowed)  
77 Shakuhachi 85 Lead 6 (voice) 93 Pad 6 (metallic)  
78 Whistle 86 Lead 7 (fifths) 94 Pad 7 (halo)  
79 Ocarina 87 Lead 8 (brass + lead) 95 Pad 8 (sweep)  
120 Guitar fret noise   
121 Breath noise   
122 Seashore   
123 Bird tweet   
124 Telephone ring   
125 Helicopter   
126 Applause   
127 Gunshot 

Автор: TP@MB@Y 10.8.2006, 23:11
Snowy,  такс... мы все ближе к истине двигаемся smile 
спасибо насчет идеи с каналами. буду искать

Автор: Snowy 10.8.2006, 23:19
Пытаюсь совладеть с этой докой http://www.compress.ru/Archive/CP/2000/9/22/part_01.htm
Но пока не удаётся задать канал. Не хочет менять пианину на другой инструмент smile

Добавлено @ 23:30 
Первая общая часть дока тут: http://www.compress.ru/Archive/CP/2000/9/22/index.htm

Автор: Агрох 3.2.2014, 16:43
Тема находится в списке избранных, но всё таки есть тут некая незавершённость.

Для указания инструмента:
Код

  midimsg := $C0+$100*t ; // t - номер инструмента, от 0 до 127
  midiOutShortMsg (hmidi, midimsg);

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)