diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-07-15 00:14:28 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-07-15 00:14:28 +0100 |
| commit | bb767c7e338414beee132af3e96829c1448e214b (patch) | |
| tree | bec2858dcc7225a9bcc2acd8170c25508f6df6cb /src/tools/fixlengths.cc | |
| parent | 66c9be6bdb1361e5681e094a0c8170d268aa9518 (diff) | |
Move things round a bit.
Diffstat (limited to 'src/tools/fixlengths.cc')
| -rw-r--r-- | src/tools/fixlengths.cc | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/src/tools/fixlengths.cc b/src/tools/fixlengths.cc new file mode 100644 index 000000000..52696cd8b --- /dev/null +++ b/src/tools/fixlengths.cc @@ -0,0 +1,209 @@ +/* + Copyright (C) 2012 Carl Hetherington <cth@carlh.net> + + 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. + +*/ + +#include <stdexcept> +#include <iostream> +#include <iomanip> +#include <getopt.h> +#include <sndfile.h> +#include <boost/filesystem.hpp> +#include "lib/film.h" + +using namespace std; +using namespace boost; + +void +help (string n) +{ + cerr << "Syntax: " << n << " [--help] [--chop-audio-start] [--chop-audio-end] --film <film>\n"; +} + +void +sox (vector<string> const & audio_files, string const & process) +{ + for (vector<string>::const_iterator i = audio_files.begin(); i != audio_files.end(); ++i) { + stringstream cmd; + cmd << "sox \"" << *i << "\" -t wav \"" << *i << ".tmp\" " << process; + cout << "> " << cmd.str() << "\n"; + int r = ::system (cmd.str().c_str()); + if (r == -1 || WEXITSTATUS (r) != 0) { + cerr << "fixlengths: call to sox failed.\n"; + exit (EXIT_FAILURE); + } + filesystem::rename (*i + ".tmp", *i); + } +} + +int main (int argc, char* argv[]) +{ + string film_dir; + bool chop_audio_start = false; + bool chop_audio_end = false; + bool pad_audio_end = false; + + while (1) { + static struct option long_options[] = { + { "help", no_argument, 0, 'h' }, + { "chop-audio-start", no_argument, 0, 'c' }, + { "chop-audio-end", no_argument, 0, 'd' }, + { "pad-audio-end", no_argument, 0, 'p' }, + { "film", required_argument, 0, 'f' }, + { 0, 0, 0, 0 } + }; + + int option_index = 0; + int c = getopt_long (argc, argv, "hcf:", long_options, &option_index); + + if (c == -1) { + break; + } + + switch (c) { + case 'h': + help (argv[0]); + exit (EXIT_SUCCESS); + case 'c': + chop_audio_start = true; + break; + case 'd': + chop_audio_end = true; + break; + case 'p': + pad_audio_end = true; + break; + case 'f': + film_dir = optarg; + break; + } + } + + if (film_dir.empty ()) { + help (argv[0]); + exit (EXIT_FAILURE); + } + + dvdomatic_setup (); + + Film* film = 0; + try { + film = new Film (film_dir, true); + } catch (std::exception& e) { + cerr << argv[0] << ": error reading film `" << film_dir << "' (" << e.what() << ")\n"; + exit (EXIT_FAILURE); + } + + /* XXX: hack */ + int video_frames = 0; + for (filesystem::directory_iterator i = filesystem::directory_iterator (film->j2k_dir()); i != filesystem::directory_iterator(); ++i) { + ++video_frames; + } + + float const video_length = video_frames / film->frames_per_second(); + cout << "Video length: " << video_length << " (" << video_frames << " frames at " << film->frames_per_second() << " frames per second).\n"; + + vector<string> audio_files = film->audio_files (); + if (audio_files.empty ()) { + cerr << argv[0] << ": film has no audio files.\n"; + exit (EXIT_FAILURE); + } + + sf_count_t audio_frames = 0; + int audio_sample_rate = 0; + + for (vector<string>::iterator i = audio_files.begin(); i != audio_files.end(); ++i) { + SF_INFO info; + info.format = 0; + SNDFILE* sf = sf_open (i->c_str(), SFM_READ, &info); + if (sf == 0) { + cerr << argv[0] << ": could not open WAV file for reading.\n"; + exit (EXIT_FAILURE); + } + + if (audio_frames == 0) { + audio_frames = info.frames; + } + + if (audio_sample_rate == 0) { + audio_sample_rate = info.samplerate; + } + + if (audio_frames != info.frames) { + cerr << argv[0] << ": audio files have differing lengths.\n"; + exit (EXIT_FAILURE); + } + + if (audio_sample_rate != info.samplerate) { + cerr << argv[0] << ": audio files have differing sample rates.\n"; + exit (EXIT_FAILURE); + } + + sf_close (sf); + } + + float const audio_length = audio_frames / float (audio_sample_rate); + + cout << "Audio length: " << audio_length << " (" << audio_frames << " frames at " << audio_sample_rate << " frames per second).\n"; + + cout << "\n"; + + if (audio_length > video_length) { + cout << setprecision (3); + cout << "Audio " << (audio_length - video_length) << "s longer than video.\n"; + + float const delta = audio_length - video_length; + int const delta_samples = delta * audio_sample_rate; + + if (chop_audio_start) { + cout << "Chopping difference off the start of the audio.\n"; + + stringstream s; + s << "trim " << delta_samples << "s"; + sox (audio_files, s.str ()); + + } else if (chop_audio_end) { + cout << "Chopping difference off the end of the audio.\n"; + + stringstream s; + s << "reverse trim " << delta_samples << "s reverse"; + sox (audio_files, s.str ()); + + } else { + cout << "Re-run with --chop-audio-start or --chop-audio-end, perhaps.\n"; + } + + } else if (audio_length < video_length) { + cout << setprecision (3); + cout << "Audio " << (video_length - audio_length) << "s shorter than video.\n"; + + if (pad_audio_end) { + + float const delta = video_length - audio_length; + int const delta_samples = delta * audio_sample_rate; + stringstream s; + s << "pad 0 " << delta_samples << "s"; + sox (audio_files, s.str ()); + + } else { + cout << "Re-run with --pad-audio-end, perhaps.\n"; + } + } + + + return 0; +} |
