123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- {
- Copyright (C) 2001 Steve Harris
- 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 impulse_grabber;
- {$MODE objfpc}{$H+}
- uses
- Jack, CTypes, SysUtils;
- var
- input_port: Pjack_port_t;
- output_port: Pjack_port_t;
- impulse_sent: Boolean = False;
- response: Pcfloat;
- response_duration: culong;
- response_pos: culong;
- grab_finished: Boolean = False;
- function process (nframes: jack_nframes_t; arg: Pointer): cint; cdecl;
- var
- _in, _out: Pjack_default_audio_sample_t;
- i: cuint;
- begin
- _out := Pjack_default_audio_sample_t(jack_port_get_buffer (output_port, nframes));
- _in := Pjack_default_audio_sample_t(jack_port_get_buffer (input_port, nframes));
- if grab_finished then
- Result := 0
- else if impulse_sent then
- begin
- i := 0;
- while (i < nframes) and (response_pos < response_duration) do
- begin
- response[response_pos] := _in[i];
- Inc(response_pos);
- Inc(i);
- end;
- if response_pos >= response_duration then
- grab_finished := True;
- for i := 0 to nframes - 1 do
- _out[i] := 0;
- end
- else
- begin
- _out[0] := 1;
- for i := 1 to nframes - 1 do
- _out[i] := 0;
- impulse_sent := True;
- end;
- Result := 0;
- end;
- procedure jack_shutdown (arg: Pointer); cdecl;
- begin
- Halt (1);
- end;
- var
- client: Pjack_client_t;
- ports: PPChar;
- fs: cfloat; // The sample rate
- peak: cfloat;
- peak_sample: culong;
- i: cuint;
- duration: cfloat = 0.0;
- c_format: Boolean = False;
- longopt_index: Integer = 0;
- show_usage: Boolean = False;
- tmpS: string;
- begin
- while longopt_index < ParamCount do
- begin
- Inc(longopt_index);
- case ParamStr(longopt_index) of
- '-h', '--help':
- begin
- show_usage := True;
- break;
- end;
- '-d', '--duration':
- begin
- Inc(longopt_index);
- if longopt_index > ParamCount then
- begin
- show_usage := True;
- break;
- end;
- duration := StrToFloat(ParamStr(longopt_index));
- end;
- '-f', '--format':
- begin
- Inc(longopt_index);
- if longopt_index > ParamCount then
- begin
- show_usage := True;
- break;
- end;
- if UpCase(ParamStr(longopt_index)) = 'C' then
- c_format := True;
- end;
- else
- begin
- show_usage := True;
- break;
- end;
- end;
- end;
- if show_usage or (duration <= 0) then
- begin
- Writeln(StdErr, 'usage: jack_impulse_grab -d duration [-f (C|gnuplot)]');
- Halt(1);
- end;
- { try to become a client of the JACK server }
- client := jack_client_open('impulse_grabber', JackNullOption, nil);
- if client = nil then
- begin
- Writeln (StdErr, 'jack server not running?');
- Halt(1);
- end;
- { tell the JACK server to call `process()' whenever
- there is work to be done.
- }
- jack_set_process_callback (client, @process, nil);
- { tell the JACK server to call `jack_shutdown()' if
- it ever shuts down, either entirely, or if it
- just decides to stop calling us.
- }
- jack_on_shutdown (client, @jack_shutdown, nil);
- { display the current sample rate. once the client is activated
- (see below), you should rely on your own sample rate
- callback (see above) for this value.
- }
- fs := jack_get_sample_rate(client);
- response_duration := Trunc(fs * duration);
- response := GetMem(response_duration * SizeOf(cfloat));
- Writeln(StdErr,
- 'Grabbing ', duration:0:12, ' seconds (', response_duration, ' samples) of impulse response');
- { create two ports }
- input_port := jack_port_register (client, 'input', JACK_DEFAULT_AUDIO_TYPE, Ord(JackPortIsInput), 0);
- output_port := jack_port_register (client, 'output', JACK_DEFAULT_AUDIO_TYPE, Ord(JackPortIsOutput), 0);
- { tell the JACK server that we are ready to roll }
- if jack_activate (client) <> 0 then
- begin
- Writeln (StdErr, 'cannot activate client');
- Halt(1);
- end;
- { connect the ports. Note: you can't do this before
- the client is activated (this may change in the future).
- }
- ports := jack_get_ports (client, nil, nil, Ord(JackPortIsPhysical) or Ord(JackPortIsOutput));
- if ports = nil then
- begin
- Writeln(StdErr, 'Cannot find any physical capture ports');
- Halt(1);
- end;
- if jack_connect (client, ports[0], jack_port_name (input_port)) <> 0 then
- begin
- Writeln (StdErr, 'cannot connect input ports');
- end;
- jack_free (ports);
- ports := jack_get_ports (client, nil, nil, Ord(JackPortIsPhysical) or Ord(JackPortIsInput));
- if ports = nil then
- begin
- Writeln(StdErr, 'Cannot find any physical playback ports');
- Halt(1);
- end;
- if jack_connect (client, jack_port_name (output_port), ports[0]) <> 0 then
- begin
- Writeln (StdErr, 'cannot connect output ports');
- end;
- jack_free (ports);
- { Wait for grab to finish }
- while not grab_finished do
- begin
- sleep (1000);
- end;
- jack_client_close (client);
- peak := response[0];
- peak_sample := 0;
- if c_format then
- begin
- Write('impulse[', response_duration, '] = {');
- for i := 0 to response_duration - 1 do
- begin
- if (i mod 4) <> 0 then
- Write(' ')
- else
- begin
- Writeln;
- Write(#9);
- end;
- WriteStr(tmpS, response[i]:0:10);
- if Pos('-', tmpS) = 0 then
- tmpS := '+' + tmpS;
- Write('"', tmpS, '"');
- if i < (response_duration - 1) then
- write(',');
- if Abs(response[i]) > peak then
- begin
- peak := Abs(response[i]);
- peak_sample := i;
- end;
- end;
- Writeln;
- Writeln('};');
- end
- else
- begin
- for i :=0 to response_duration - 1 do
- begin
- Writeln(response[i]:0:12);
- if Abs(response[i]) > peak then
- begin
- peak := Abs(response[i]);
- peak_sample := i;
- end;
- end;
- end;
- Writeln(StdErr, 'Peak value was ', peak:0:12, ' at sample ', peak_sample);
- Halt (0);
- end.
|