2 Copyright (C) 2002 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "ardour/ardour.h"
24 #include "ardour/session.h"
25 #include "ardour/tempo.h"
26 #include "ardour/io.h"
27 #include "ardour/buffer_set.h"
28 #include "ardour/audio_buffer.h"
35 using namespace ARDOUR
;
38 Pool
Click::pool ("click", sizeof (Click
), 128);
41 Session::click (framepos_t start
, framecnt_t nframes
)
43 TempoMap::BBTPointList
*points
;
50 Glib::RWLock::WriterLock
clickm (click_lock
, Glib::TRY_LOCK
);
52 if (!clickm
.locked() || _transport_speed
!= 1.0 || !_clicking
|| click_data
== 0) {
53 _click_io
->silence (nframes
);
57 const framepos_t end
= start
+ nframes
;
59 BufferSet
& bufs
= get_scratch_buffers(ChanCount(DataType::AUDIO
, 1));
60 buf
= bufs
.get_audio(0).data();
61 points
= _tempo_map
->get_points (start
, end
);
67 if (points
->empty()) {
72 for (TempoMap::BBTPointList::iterator i
= points
->begin(); i
!= points
->end(); ++i
) {
75 if (click_emphasis_data
== 0 || (click_emphasis_data
&& (*i
).beat
!= 1)) {
76 clicks
.push_back (new Click ((*i
).frame
, click_length
, click_data
));
81 if (click_emphasis_data
) {
82 clicks
.push_back (new Click ((*i
).frame
, click_emphasis_length
, click_emphasis_data
));
89 memset (buf
, 0, sizeof (Sample
) * nframes
);
91 for (list
<Click
*>::iterator i
= clicks
.begin(); i
!= clicks
.end(); ) {
94 framecnt_t internal_offset
;
96 list
<Click
*>::iterator next
;
102 if (clk
->start
< start
) {
105 internal_offset
= clk
->start
- start
;
108 if (nframes
< internal_offset
) {
109 /* we've just located or something..
110 effectively going backwards.
111 lets get the flock out of here */
115 copy
= min (clk
->duration
- clk
->offset
, nframes
- internal_offset
);
117 memcpy (buf
+ internal_offset
, &clk
->data
[clk
->offset
], copy
* sizeof (Sample
));
121 if (clk
->offset
>= clk
->duration
) {
130 _click_io
->copy_to_outputs (bufs
, DataType::AUDIO
, nframes
, 0);
134 Session::setup_click_sounds (Sample
** data
, Sample
const * default_data
, framecnt_t
* length
, framecnt_t default_length
, string
const & path
)
136 if (*data
!= default_data
) {
143 *data
= const_cast<Sample
*> (default_data
);
144 *length
= default_length
;
152 if ((sndfile
= sf_open (path
.c_str(), SFM_READ
, &info
)) == 0) {
154 sf_error_str (0, errbuf
, sizeof (errbuf
) - 1);
155 warning
<< string_compose (_("cannot open click soundfile %1 (%2)"), path
, errbuf
) << endmsg
;
160 /* read the (possibly multi-channel) click data into a temporary buffer */
162 sf_count_t
const samples
= info
.frames
* info
.channels
;
164 Sample
* tmp
= new Sample
[samples
];
166 if (sf_readf_float (sndfile
, tmp
, info
.frames
) != info
.frames
) {
168 warning
<< _("cannot read data from click soundfile") << endmsg
;
174 *data
= new Sample
[info
.frames
];
175 *length
= info
.frames
;
177 /* mix down to mono */
179 for (int i
= 0; i
< info
.frames
; ++i
) {
181 for (int j
= 0; j
< info
.channels
; ++j
) {
182 (*data
)[i
] = tmp
[i
* info
.channels
+ j
];
184 (*data
)[i
] /= info
.channels
;
194 Session::setup_click_sounds (int which
)
198 if (which
== 0 || which
== 1) {
203 default_click_length
,
204 Config
->get_click_sound ()
208 if (which
== 0 || which
== -1) {
210 &click_emphasis_data
,
211 default_click_emphasis
,
212 &click_emphasis_length
,
213 default_click_emphasis_length
,
214 Config
->get_click_emphasis_sound ()
220 Session::clear_clicks ()
222 Glib::RWLock::WriterLock
lm (click_lock
);
224 for (Clicks::iterator i
= clicks
.begin(); i
!= clicks
.end(); ++i
) {