Browse Source

+ added libjack example program midiseq.pp (translated from midiseq.c)

Nikolay Nikolov 7 months ago
parent
commit
3123101b0c
2 changed files with 146 additions and 0 deletions
  1. 145 0
      packages/libjack/examples/midiseq.pp
  2. 1 0
      packages/libjack/fpmake.pp

+ 145 - 0
packages/libjack/examples/midiseq.pp

@@ -0,0 +1,145 @@
+{
+    Copyright (C) 2004 Ian Esten
+    
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+}
+
+program midiseq;
+
+{$MODE objfpc}{$H+}
+
+uses
+  CTypes, SysUtils, BaseUnix, Jack, JackMidiPort;
+
+var
+  client: Pjack_client_t;
+  output_port: Pjack_port_t;
+
+  note_frqs: Pcuchar;
+  note_starts: Pjack_nframes_t;
+  note_lengths: Pjack_nframes_t;
+  num_notes: jack_nframes_t;
+  loop_nsamp: jack_nframes_t;
+  loop_index: jack_nframes_t;
+
+procedure signal_handler(sig: cint); cdecl;
+begin
+  jack_client_close(client);
+  Writeln(StdErr, 'signal received, exiting ...');
+  Halt(0);
+end;
+
+procedure usage;
+begin
+  WriteLn(StdErr, 'usage: jack_midiseq name nsamp [startindex note nsamp] ...... [startindex note nsamp]');
+  WriteLn(StdErr, 'eg: jack_midiseq Sequencer 24000 0 60 8000 12000 63 8000');
+  WriteLn(StdErr, 'will play a 1/2 sec loop (if srate is 48khz) with a c4 note at the start of the loop');
+  WriteLn(StdErr, 'that lasts for 12000 samples, then a d4# that starts at 1/4 sec that lasts for 800 samples');
+end;
+
+function process(nframes: jack_nframes_t; arg: Pointer): cint; cdecl;
+var
+  i, j: cint;
+  port_buf: Pointer;
+  buffer: Pcuchar;
+begin
+  port_buf := jack_port_get_buffer(output_port, nframes);
+  jack_midi_clear_buffer(port_buf);
+  {FillChar(buffer^, nframes*SizeOf(jack_default_audio_sample_t), 0);}
+
+  for i := 0 to nframes - 1 do
+  begin
+    for j := 0 to num_notes - 1 do
+    begin
+      if note_starts[j] = loop_index then
+      begin
+	buffer := jack_midi_event_reserve(port_buf, i, 3);
+	{printf("wrote a note on, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);}
+	buffer[2] := 64;        { velocity }
+	buffer[1] := note_frqs[j];
+	buffer[0] := $90;       { note on }
+      end
+      else if (note_starts[j] + note_lengths[j]) = loop_index then
+      begin
+	buffer := jack_midi_event_reserve(port_buf, i, 3);
+	{printf("wrote a note off, port buffer = 0x%x, event buffer = 0x%x\n", port_buf, buffer);}
+	buffer[2] := 64;        { velocity }
+	buffer[1] := note_frqs[j];
+	buffer[0] := $80;       { note off }
+      end;
+    end;
+    if loop_index + 1 >= loop_nsamp then
+      loop_index := 0
+    else
+      loop_index := loop_index + 1;
+  end;
+  Result := 0;
+end;
+
+var
+  i: cint;
+  nframes: jack_nframes_t;
+  client_name: string;
+begin
+  if (ParamCount<5) or ((ParamCount-2) mod 3 <> 0) then
+  begin
+    usage;
+    Halt(1);
+  end;
+  client_name := ParamStr(1);
+  client := jack_client_open (PChar(client_name), JackNullOption, nil);
+  if client = nil then
+  begin
+    Writeln (StdErr, 'JACK server not running?');
+    Halt(1);
+  end;
+  jack_set_process_callback (client, @process, nil);
+  output_port := jack_port_register (client, 'out', JACK_DEFAULT_MIDI_TYPE, Ord(JackPortIsOutput), 0);
+  nframes := jack_get_buffer_size(client);
+  loop_index := 0;
+  num_notes := (ParamCount - 2) div 3;
+  note_frqs := GetMem(num_notes*SizeOf(cuchar));
+  note_starts := GetMem(num_notes*SizeOf(jack_nframes_t));
+  note_lengths := GetMem(num_notes*SizeOf(jack_nframes_t));
+  loop_nsamp := StrToInt(ParamStr(2));
+  for i := 0 to num_notes - 1 do
+  begin
+    note_starts[i] := StrToInt(ParamStr(3 + 3*i));
+    note_frqs[i] := StrToInt(ParamStr(4 + 3*i));
+    note_lengths[i] := StrToInt(ParamStr(5 + 3*i));
+  end;
+
+  if jack_activate(client) <> 0 then
+  begin
+    Writeln (StdErr, 'cannot activate client');
+    Halt(1);
+  end;
+
+  { install a signal handler to properly quits jack client }
+{$ifndef WIN32}
+  fpsignal(SIGQUIT, @signal_handler);
+  fpsignal(SIGHUP, @signal_handler);
+{$endif}
+  fpsignal(SIGTERM, @signal_handler);
+  fpsignal(SIGINT, @signal_handler);
+
+  { run until interrupted }
+  repeat
+    Sleep(1000);
+  until False;
+
+  jack_client_close(client);
+  Halt (0);
+end.

+ 1 - 0
packages/libjack/fpmake.pp

@@ -128,6 +128,7 @@ begin
     P.Targets.AddExampleProgram('impulse_grabber.pp');
     P.Targets.AddExampleProgram('showtime.pp');
     P.Targets.AddExampleProgram('midisine.pp');
+    P.Targets.AddExampleProgram('midiseq.pp');
 
     P.NamespaceMap:='namespaces.lst';