multimedia_paradise 1.1.344 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +99 -77
  3. data/bin/audio_player +1 -1
  4. data/bin/extract_images_from_this_video_file +1 -1
  5. data/bin/loop_this_video +1 -1
  6. data/bin/merge_avi_files +1 -1
  7. data/bin/merge_mp3 +1 -1
  8. data/bin/mp3_to_opus +1 -1
  9. data/bin/mpg_to_mp4 +1 -1
  10. data/bin/multimedia_paradise +1 -1
  11. data/bin/to_aiff +2 -5
  12. data/bin/to_flac +7 -0
  13. data/bin/to_mp3 +8 -0
  14. data/bin/to_mp4 +1 -1
  15. data/bin/to_ogg +7 -0
  16. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +1 -1
  17. data/bin/video_codec +1 -1
  18. data/bin/video_thumbnail +1 -1
  19. data/bin/video_to_images +1 -1
  20. data/doc/README.gen +88 -51
  21. data/doc/{CHANGELOG.md → changelog/changelog.md} +8 -6
  22. data/doc/{LINKS.md → links/links.md} +2 -2
  23. data/doc/{MOTIVATION_FOR_THIS_PROJECT.md → motivation_for_the_multimedia_paradise_project/motivation_for_the_multimedia_paradise_project.md} +5 -5
  24. data/doc/todo/todo_for_the_multimedia_paradise_project.md +79 -93
  25. data/lib/multimedia_paradise/actions/actions.rb +224 -0
  26. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +61 -64
  27. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +17 -8
  28. data/lib/multimedia_paradise/audio/base.rb +0 -5
  29. data/lib/multimedia_paradise/audio/compress.rb +8 -5
  30. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +7 -11
  31. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +0 -37
  32. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +90 -68
  33. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +134 -80
  34. data/lib/multimedia_paradise/audio/genres/boogie.rb +1 -6
  35. data/lib/multimedia_paradise/audio/genres/concerts.rb +1 -6
  36. data/lib/multimedia_paradise/audio/genres/constants.rb +1 -1
  37. data/lib/multimedia_paradise/audio/genres/eurodance.rb +1 -6
  38. data/lib/multimedia_paradise/audio/genres/genre.rb +36 -33
  39. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +1 -6
  40. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +1 -6
  41. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +1 -6
  42. data/lib/multimedia_paradise/audio/genres/trance.rb +4 -7
  43. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +27 -22
  44. data/lib/multimedia_paradise/audio/merge_audio_files.rb +18 -11
  45. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +23 -11
  46. data/lib/multimedia_paradise/audio/n_audio_songs.rb +3 -2
  47. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +41 -16
  48. data/lib/multimedia_paradise/audio/playlist/playlist.rb +163 -123
  49. data/lib/multimedia_paradise/audio/remove_audio.rb +11 -6
  50. data/lib/multimedia_paradise/audio/remove_last_second.rb +2 -3
  51. data/lib/multimedia_paradise/audio/report_missing_id.rb +22 -12
  52. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +7 -5
  53. data/lib/multimedia_paradise/audio/to_mp3.rb +7 -5
  54. data/lib/multimedia_paradise/audio/to_ogg.rb +3 -1
  55. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +5 -5
  56. data/lib/multimedia_paradise/base/base.rb +854 -15
  57. data/lib/multimedia_paradise/base/colours.rb +28 -31
  58. data/lib/multimedia_paradise/base/{commandline_arguments.rb → commandline_arguments_module/commandline_arguments_module.rb} +12 -9
  59. data/lib/multimedia_paradise/colours/colours.rb +4 -1
  60. data/lib/multimedia_paradise/commandline/{menu.rb → commandline.rb} +19 -16
  61. data/lib/multimedia_paradise/constants/constants.rb +504 -14
  62. data/lib/multimedia_paradise/constants/web_constants.rb +2 -4
  63. data/lib/multimedia_paradise/gui/gui_base.rb +2 -2
  64. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +1 -1
  65. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +1 -1
  66. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +1 -1
  67. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +1 -1
  68. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +0 -478
  69. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +94 -41
  70. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +0 -257
  71. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/change_metadata_widget.rb +2 -2
  72. data/lib/multimedia_paradise/gui/universal_widgets/information_about_a_mp3_file/information_about_a_mp3_file.rb +1 -1
  73. data/lib/multimedia_paradise/gui/universal_widgets/lyrics/lyrics.rb +1 -1
  74. data/lib/multimedia_paradise/gui/universal_widgets/multimedia_converter/multimedia_converter.rb +589 -0
  75. data/lib/multimedia_paradise/gui/universal_widgets/playlist/playlist.rb +197 -0
  76. data/lib/multimedia_paradise/gui/universal_widgets/radio/radio.rb +1 -1
  77. data/lib/multimedia_paradise/gui/{gtk2 → universal_widgets}/simple_play_widget/README.md +1 -1
  78. data/lib/multimedia_paradise/gui/universal_widgets/simple_play_widget/simple_play_widget.rb +404 -0
  79. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.rb +3 -6
  80. data/lib/multimedia_paradise/java/Playlist.class +0 -0
  81. data/lib/multimedia_paradise/java/Playlist.java +198 -0
  82. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +21 -19
  83. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +441 -442
  84. data/lib/multimedia_paradise/multimedia/base.rb +0 -18
  85. data/lib/multimedia_paradise/multimedia/chord.rb +1 -1
  86. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +7 -5
  87. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +2 -2
  88. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +22 -3
  89. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +4 -3
  90. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +4 -27
  91. data/lib/multimedia_paradise/multimedia/{read_meta_tags.rb → read_meta_tags/read_meta_tags.rb} +14 -19
  92. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +3 -3
  93. data/lib/multimedia_paradise/project/project.rb +8 -4
  94. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +5 -5
  95. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +1 -1
  96. data/lib/multimedia_paradise/sinatra/app.rb +3 -3
  97. data/lib/multimedia_paradise/statistics/README.md +6 -5
  98. data/lib/multimedia_paradise/statistics/video.rb +34 -14
  99. data/lib/multimedia_paradise/{misc → time}/long_format_to_milliseconds_converter.rb +4 -2
  100. data/lib/multimedia_paradise/{misc → time}/milliseconds_to_long_format_converter.rb +2 -2
  101. data/lib/multimedia_paradise/toplevel_methods/audio_related_code.rb +138 -0
  102. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +2 -2
  103. data/lib/multimedia_paradise/{conversions → toplevel_methods}/conversions.rb +140 -48
  104. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +5 -5
  105. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +7 -6
  106. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +2 -2
  107. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +2 -2
  108. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +3 -6
  109. data/lib/multimedia_paradise/toplevel_methods/{output_directory.rb → directory_related_code.rb} +38 -1
  110. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +8 -4
  111. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -4
  112. data/lib/multimedia_paradise/{ffmpeg → toplevel_methods}/ffmpeg.rb +200 -193
  113. data/lib/multimedia_paradise/toplevel_methods/{files_and_directories.rb → files_related_code.rb} +19 -56
  114. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +3 -3
  115. data/lib/multimedia_paradise/toplevel_methods/is_audio_file_is_video_file_is_image_file_is_multimedia_file.rb +115 -0
  116. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +1 -1
  117. data/lib/multimedia_paradise/toplevel_methods/{merge_multimedia_file.rb → merge.rb} +98 -4
  118. data/lib/multimedia_paradise/toplevel_methods/opn.rb +5 -4
  119. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +14 -7
  120. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +4 -3
  121. data/lib/multimedia_paradise/toplevel_methods/radio.rb +1 -3
  122. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +4 -4
  123. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +1 -1
  124. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +9 -7
  125. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +3 -4
  126. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +6 -6
  127. data/lib/multimedia_paradise/{help/help.rb → toplevel_methods/show_help.rb} +14 -8
  128. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +2 -3
  129. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +3 -2
  130. data/lib/multimedia_paradise/toplevel_methods/{misc.rb → toplevel_methods.rb} +485 -527
  131. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +4 -3
  132. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +1 -2
  133. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +1 -1
  134. data/lib/multimedia_paradise/version/version.rb +2 -2
  135. data/lib/multimedia_paradise/video/all_videos.rb +12 -19
  136. data/lib/multimedia_paradise/video/check_numbers.rb +76 -32
  137. data/lib/multimedia_paradise/video/columbo/columbo.rb +36 -14
  138. data/lib/multimedia_paradise/video/guess_video_name.rb +2 -10
  139. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +2 -2
  140. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +1 -9
  141. data/lib/multimedia_paradise/video/movie_searcher.rb +2 -10
  142. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +1 -9
  143. data/lib/multimedia_paradise/video/random_video.rb +1 -2
  144. data/lib/multimedia_paradise/video/registered_video_file.rb +2 -10
  145. data/lib/multimedia_paradise/video/report_local_videos.rb +1 -9
  146. data/lib/multimedia_paradise/video/simpsons.rb +2 -10
  147. data/lib/multimedia_paradise/video/smart_animals/smart_animals.rb +10 -8
  148. data/lib/multimedia_paradise/video/speed_up_video.rb +28 -10
  149. data/lib/multimedia_paradise/video/store_available_video_files.rb +49 -33
  150. data/lib/multimedia_paradise/video/the_simpsons/README.md +0 -0
  151. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +8 -8
  152. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +14 -10
  153. data/lib/multimedia_paradise/video/video_information.rb +55 -49
  154. data/lib/multimedia_paradise/{configuration → yaml/configuration}/play_zoomed.yml +0 -0
  155. data/lib/multimedia_paradise/yaml/{playlist.yml → playlist/playlist.yml} +14 -15
  156. data/lib/multimedia_paradise/yaml/video/video.yml +1 -1
  157. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +34 -32
  158. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +61 -11
  159. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +5 -3
  160. data/multimedia_paradise.gemspec +1 -1
  161. data/test/testing_audio_player.rb +3 -3
  162. data/test/testing_file_duration.rb +5 -5
  163. metadata +45 -76
  164. data/lib/multimedia_paradise/audio/file_duration/constants.rb +0 -53
  165. data/lib/multimedia_paradise/audio/waveform/class.rb +0 -341
  166. data/lib/multimedia_paradise/audio/waveform/constants.rb +0 -38
  167. data/lib/multimedia_paradise/audio/waveform/log.rb +0 -101
  168. data/lib/multimedia_paradise/base/constants.rb +0 -19
  169. data/lib/multimedia_paradise/base/encoding.rb +0 -31
  170. data/lib/multimedia_paradise/base/misc.rb +0 -665
  171. data/lib/multimedia_paradise/base/namespace.rb +0 -36
  172. data/lib/multimedia_paradise/base/time.rb +0 -25
  173. data/lib/multimedia_paradise/constants/conversions.rb +0 -62
  174. data/lib/multimedia_paradise/constants/directory_constants.rb +0 -139
  175. data/lib/multimedia_paradise/constants/encodings.rb +0 -26
  176. data/lib/multimedia_paradise/constants/file_constants.rb +0 -176
  177. data/lib/multimedia_paradise/constants/misc.rb +0 -80
  178. data/lib/multimedia_paradise/constants/my_video_directory.rb +0 -30
  179. data/lib/multimedia_paradise/constants/namespace.rb +0 -14
  180. data/lib/multimedia_paradise/constants/newline.rb +0 -14
  181. data/lib/multimedia_paradise/constants/video_filetypes.rb +0 -27
  182. data/lib/multimedia_paradise/conversions/README.md +0 -2
  183. data/lib/multimedia_paradise/ffmpeg/README.md +0 -2
  184. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +0 -33
  185. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +0 -144
  186. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +0 -43
  187. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +0 -40
  188. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +0 -42
  189. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +0 -32
  190. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +0 -0
  191. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +0 -34
  192. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +0 -34
  193. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +0 -38
  194. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +0 -31
  195. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +0 -50
  196. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +0 -18
  197. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +0 -31
  198. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +0 -27
  199. data/lib/multimedia_paradise/toplevel_methods/has_audio.rb +0 -48
  200. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +0 -61
  201. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +0 -27
  202. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +0 -27
  203. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +0 -31
  204. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +0 -62
  205. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +0 -106
  206. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +0 -30
  207. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +0 -30
  208. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +0 -24
  209. /data/doc/{MergingVideoLectures.md → merging_video_lectures/merging_video_lectures.md} +0 -0
  210. /data/doc/{Readme_for_the_cut_audio_component.md → readme_for_the_cut_audio_component/Readme_for_the_cut_audio_component.md} +0 -0
  211. /data/lib/multimedia_paradise/yaml/{audio_formats.yml → audio_formats/audio_formats.yml} +0 -0
  212. /data/lib/multimedia_paradise/yaml/{image_formats.yml → image_formats/image_formats.yml} +0 -0
  213. /data/lib/multimedia_paradise/yaml/{lyrics.yml → lyrics/lyrics.yml} +0 -0
  214. /data/lib/multimedia_paradise/yaml/{music_genres.yml → music_genres/music_genres.yml} +0 -0
  215. /data/lib/multimedia_paradise/yaml/{song_tags.yml → song_tags/song_tags.yml} +0 -0
  216. /data/lib/multimedia_paradise/yaml/{use_this_video_player.yml → use_this_video_player/use_this_video_player.yml} +0 -0
  217. /data/lib/multimedia_paradise/yaml/{video_encoding_settings.yml → video_encoding_settings/video_encoding_settings.yml} +0 -0
  218. /data/lib/multimedia_paradise/yaml/{video_filter_aliases.yml → video_filter_aliases/video_filter_aliases.yml} +0 -0
@@ -1,341 +0,0 @@
1
- #!/usr/bin/ruby -w
2
- # Encoding: UTF-8
3
- # frozen_string_literal: true
4
- # =========================================================================== #
5
- # require 'multimedia_paradise/audio/waveform/class.rb'
6
- # =========================================================================== #
7
- require 'multimedia_paradise/audio/waveform/constants.rb'
8
- require 'multimedia_paradise/audio/waveform/log.rb'
9
- require 'multimedia_paradise/base/base.rb'
10
-
11
- module MultimediaParadise
12
-
13
- class Waveform < Base # === MultimediaParadise::Waveform
14
-
15
- begin
16
- require 'ruby-audio'
17
- rescue LoadError; end
18
-
19
- # ========================================================================= #
20
- # === NAMESPACE
21
- # ========================================================================= #
22
- NAMESPACE = inspect
23
-
24
- begin
25
- require 'oily_png'
26
- rescue LoadError
27
- begin
28
- require 'chunky_png'
29
- rescue LoadError
30
- # ===================================================================== #
31
- # If we are on my home system, report that chunky_png is missing.
32
- # ===================================================================== #
33
- if ENV['IS_ROEBE'].to_s == '1'
34
- opn(namespace: NAMESPACE)
35
- puts 'chunky_png is missing - please install it.'
36
- end
37
- end
38
- end
39
-
40
- # ========================================================================= #
41
- # Scope these under Waveform so you can catch the ones generated by
42
- # just this class.
43
- # ========================================================================= #
44
- class RuntimeError < ::RuntimeError; end
45
- class ArgumentError < ::ArgumentError; end
46
-
47
- # ========================================================================= #
48
- # === MultimediaParadise::Waveform.generate (generate tag)
49
- #
50
- # This method will generate a waveform image.
51
- #
52
- # The first argument will be the input-filename of the .wav file in
53
- # question.
54
- #
55
- # The second argument shall be the output name of the newly generated
56
- # filename.
57
- #
58
- # The third argument shall be the options.
59
- #
60
- # Available options, all of which are optional, are these here:
61
- #
62
- # :method => The method used to read sample frames, available methods
63
- # are peak and rms. peak is probably what you're used to seeing, it
64
- # uses the maximum amplitude per sample to generate the waveform, so
65
- # the waveform looks more dynamic. RMS gives a more fluid waveform
66
- # and probably more accurately reflects what you hear, but isn't as
67
- # pronounced (typically).
68
- #
69
- # Can be :rms or :peak
70
- #
71
- # Default is :peak.
72
- #
73
- # :width => The width (in pixels) of the final waveform image.
74
- #
75
- # Default is 1800.
76
- #
77
- # :height => The height (in pixels) of the final waveform image.
78
- #
79
- # Default is 280.
80
- #
81
- # :background_color => Hex code of the background color of the
82
- # generated waveform image.
83
- # Default is #666666 (gray).
84
- #
85
- # :color => Hex code of the color to draw the waveform, or can pass
86
- # :transparent to render the waveform transparent (use w/ a solid
87
- # color background to achieve a "cutout" effect).
88
- # Default is #00ccff (cyan-ish).
89
- #
90
- # :force => Force generation of waveform, overwriting WAV or PNG file.
91
- #
92
- # :logger => IOStream to log progress to.
93
- #
94
- # Usage examples:
95
- #
96
- # x = MultimediaParadise::Waveform.generate('foo.wav')
97
- # x = MultimediaParadise::Waveform.generate('foo.wav', 'BOTY.png')
98
- # x = MultimediaParadise::Waveform.generate('Kickstart My Heart.wav', "Kickstart My Heart.png")
99
- # x = MultimediaParadise::Waveform.generate('Kickstart My Heart.wav', "Kickstart My Heart.png", :method => :rms)
100
- # x = MultimediaParadise::Waveform.generate('Kickstart My Heart.wav', "Kickstart My Heart.png", :color => "#ff00ff", :logger => $stdout)
101
- #
102
- # ========================================================================= #
103
- def self.generate(
104
- source,
105
- filename = :guess_from_given_source,
106
- options = {}
107
- )
108
- options = DEFAULT_OPTIONS.merge(options)
109
- case filename
110
- when :guess_from_given_source, :default # Replace.
111
- filename = source.gsub(/\.wav$/,'')+'.png'
112
- end
113
- raise ArgumentError.new(
114
- 'No source audio filename given, must be an existing sound file.'
115
- ) unless source
116
- raise ArgumentError.new(
117
- 'No destination filename given for waveform.'
118
- ) unless filename
119
- raise RuntimeError.new(
120
- "Source audio file '#{source}' not found."
121
- ) unless File.exist?(source)
122
- raise RuntimeError.new(
123
- "Destination file #{filename} exists. Use --force if you want to automatically remove it."
124
- ) if File.exist?(filename) && !options[:force] === true
125
-
126
- if source.end_with? '.mp3' # User did input a .mp3 file.
127
- # ===================================================================== #
128
- # === Tap into the toplevel-method MultimediaParadise.mp3_to_wav next
129
- # ===================================================================== #
130
- source = MultimediaParadise.mp3_to_wav(source)
131
- end
132
-
133
- # ======================================================================= #
134
- # === Start the logger classer
135
- # ======================================================================= #
136
- @log = Log.new(options[:logger])
137
- @log.start!
138
- # ======================================================================= #
139
- # Frames gives the amplitudes for each channel, for our waveform we're
140
- # saying the "visual" amplitude is the average of the amplitude across
141
- # all the channels. This might be a little weird w/ the "peak" method
142
- # if the frames are very wide (i.e. the image width is very small) --
143
- # I *think* the larger the frames are, the more "peaky" the waveform
144
- # should get, perhaps to the point of inaccurately reflecting the
145
- # actual sound.
146
- # ======================================================================= #
147
- samples = frames(source, options[:width], options[:method]).map { |frame|
148
- frame.inject(0.0) { |sum, peak| sum + peak } / frame.size
149
- }
150
-
151
- @log.timed("\nDrawing...") {
152
- # ===================================================================== #
153
- # Don't remove the file even if force is true until we're sure
154
- # the source was readable.
155
- # ===================================================================== #
156
- if File.exist?(filename) && options[:force] === true
157
- @log.out("Output file #{filename} encountered. Removing.")
158
- File.delete(filename)
159
- end
160
- image = draw(samples, options)
161
- image.save(filename)
162
- }
163
- @log.done!("Generated waveform '#{filename}'")
164
- end
165
-
166
- # ========================================================================= #
167
- # === Wavelength.draw
168
- #
169
- # Draws the given samples using the given options.
170
- #
171
- # Will return a ChunkyPNG::Image.
172
- # ========================================================================= #
173
- def self.draw(samples, options)
174
- image = ChunkyPNG::Image.new(options[:width], options[:height],
175
- options[:background_color] == :transparent ? ChunkyPNG::Color::TRANSPARENT : options[:background_color]
176
- )
177
-
178
- case options[:color]
179
- # ======================================================================= #
180
- # === :transparent
181
- # ======================================================================= #
182
- when :transparent
183
- color = transparent = ChunkyPNG::Color.from_hex(
184
- # =================================================================== #
185
- # Have to do this little bit because it's possible the color we were
186
- # intending to use a transparency mask *is* the background color,
187
- # and then we would end up wiping out the whole image.
188
- # =================================================================== #
189
- options[:background_color].downcase == TRANSPARENCY_MASK ? TRANSPARENCY_ALTERNATE : TRANSPARENCY_MASK
190
- )
191
- else # Delegate towards class ChunkyPNG next.
192
- color = ChunkyPNG::Color.from_hex(options[:color])
193
- end
194
-
195
- # ======================================================================= #
196
- # Calling "zero" the middle of the waveform, like there's positive
197
- # and negative amplitude
198
- # ======================================================================= #
199
- zero = options[:height] / 2.0
200
-
201
- samples.each_with_index { |sample, x|
202
- # ===================================================================== #
203
- # Half the amplitude goes above zero, half below
204
- # ===================================================================== #
205
- amplitude = sample * options[:height].to_f / 2.0
206
- # ===================================================================== #
207
- # If you give ChunkyPNG floats for pixel positions all sorts of
208
- # things go haywire.
209
- # ===================================================================== #
210
- image.line(x, (zero - amplitude).round, x, (zero + amplitude).round, color)
211
- }
212
-
213
- # ======================================================================= #
214
- # Simple transparency masking, it just loops over every pixel and
215
- # makes ones which match the transparency mask color completely clear.
216
- # ======================================================================= #
217
- if transparent
218
- (0..image.width - 1).each { |x|
219
- (0..image.height - 1).each { |y|
220
- image[x, y] = ChunkyPNG::Color.rgba(0, 0, 0, 0) if image[x, y] == transparent
221
- }
222
- }
223
- end
224
- image
225
- end
226
-
227
- # ========================================================================= #
228
- # === source?
229
- # ========================================================================= #
230
- def source?
231
- @source
232
- end; alias source source? # === source
233
-
234
- class << self
235
-
236
- private
237
-
238
- # ======================================================================= #
239
- # === Wavelength.frames
240
- #
241
- # Returns a sampling of frames from the given RubyAudio::Sound using the
242
- # given method the sample size is determined by the given pixel width --
243
- # we want one sample frame per horizontal pixel.
244
- # ======================================================================= #
245
- def frames(source, width, method = :peak)
246
- unless %i( peak rms ).include?(method)
247
- raise ArgumentError.new("Unknown sampling method #{method}")
248
- end
249
-
250
- frames = []
251
-
252
- RubyAudio::Sound.open(source) { |audio|
253
- frames_per_sample = (audio.info.frames.to_f / width.to_f).to_i
254
- sample = RubyAudio::Buffer.new("float", frames_per_sample, audio.info.channels)
255
- @log.timed("Sampling #{frames_per_sample} frames per sample: ") {
256
- while(audio.read(sample)) > 0
257
- frames << send(method, sample, audio.info.channels)
258
- @log.out('.')
259
- end
260
- }
261
- }
262
- frames # Return the found frames here.
263
- rescue RubyAudio::Error => e
264
- raise e unless e.message == 'File contains data in an unknown format.'
265
- raise Waveform::RuntimeError.new(
266
- "Source audio file #{source} could not be read by RubyAudio "\
267
- "library -- Hint: non-WAV files are no longer supported, convert "\
268
- "to WAV first using something like ffmpeg (RubyAudio: #{e.message})"
269
- )
270
- end
271
-
272
- # ======================================================================= #
273
- # === Wavelength.peak
274
- #
275
- # Returns an array of the peak of each channel for the given collection
276
- # of frames -- the peak is individual to the channel, and the returned
277
- # collection of peaks are not (necessarily) from the same frame(s).
278
- # ======================================================================= #
279
- def peak(frames, channels = 1)
280
- peak_frame = []
281
- (0..channels-1).each { |channel|
282
- peak_frame << channel_peak(frames, channel)
283
- }
284
- peak_frame
285
- end
286
-
287
- # ======================================================================= #
288
- # === Wavelength.rms
289
- #
290
- # Returns an array of rms values for the given frameset where each
291
- # rms value is the rms value for that channel.
292
- # ======================================================================= #
293
- def rms(frames, channels = 1)
294
- rms_frame = []
295
- (0..channels-1).each { |channel|
296
- rms_frame << channel_rms(frames, channel)
297
- }
298
- rms_frame
299
- end
300
-
301
- # ======================================================================= #
302
- # === Wavelength.channel_peak
303
- #
304
- # Returns the peak voltage reached on the given channel in the given
305
- # collection of frames.
306
- #
307
- # TODO:
308
- #
309
- # Could lose some resolution and only sample every other frame, would
310
- # likely still generate the same waveform as the waveform is so
311
- # comparitively low resolution to the original input (in most cases),
312
- # and would increase the analyzation speed (maybe).
313
- # ======================================================================= #
314
- def channel_peak(frames, channel = 0)
315
- peak = 0.0
316
- frames.each { |frame|
317
- next if frame.nil?
318
- frame = Array(frame)
319
- peak = frame[channel].abs if frame[channel].abs > peak
320
- }
321
- peak
322
- end
323
-
324
- # ======================================================================= #
325
- # === Wavelength.channel_rms
326
- #
327
- # Returns the rms value across the given collection of frames
328
- # for the given channel.
329
- # ======================================================================= #
330
- def channel_rms(frames, channel = 0)
331
- Math.sqrt(frames.inject(0.0){ |sum, frame|
332
- sum += (frame ? Array(frame)[channel] ** 2 : 0) } / frames.size
333
- )
334
- end
335
- end
336
-
337
- end; end
338
-
339
- if __FILE__ == $PROGRAM_NAME
340
- MultimediaParadise::Waveform.generate(ARGV.first)
341
- end
@@ -1,38 +0,0 @@
1
- #!/usr/bin/ruby -w
2
- # Encoding: UTF-8
3
- # frozen_string_literal: true
4
- # =========================================================================== #
5
- # require 'multimedia_paradise/audio/waveform/constants.rb'
6
- # =========================================================================== #
7
- module MultimediaParadise
8
-
9
- class Waveform < ::MultimediaParadise::Base # === MultimediaParadise::Waveform
10
-
11
- # ========================================================================= #
12
- # === MultimediaParadise::Waveform::DEFAULT_OPTIONS
13
- #
14
- # Specify some default options to use for class Waveform.
15
- # ========================================================================= #
16
- DEFAULT_OPTIONS = {
17
- :method => :peak,
18
- :width => 1800,
19
- :height => 280,
20
- :background_color => '#666666',
21
- :color => '#00ccff',
22
- :force => false,
23
- :logger => nil
24
- }
25
-
26
- # ========================================================================= #
27
- # === MultimediaParadise::Waveform::TRANSPARENCY_MASK
28
- # ========================================================================= #
29
- TRANSPARENCY_MASK = '#00ff00'
30
-
31
- # ========================================================================= #
32
- # === MultimediaParadise::Waveform::TRANSPARENCY_ALTERNATE
33
- #
34
- # In case the mask is the background color!
35
- # ========================================================================= #
36
- TRANSPARENCY_ALTERNATE = '#ffff00'
37
-
38
- end; end
@@ -1,101 +0,0 @@
1
- #!/usr/bin/ruby -w
2
- # Encoding: UTF-8
3
- # frozen_string_literal: true
4
- # =========================================================================== #
5
- # === MultimediaParadise::Waveform::Log
6
- #
7
- # The purpose of this class is to log and provide benchmarks.
8
- #
9
- # This may be important for lengthy batch operations.
10
- #
11
- # There may be other, better benchmark classes, but it is fairly trivial
12
- # code - not mandatory to google for better solutions.
13
- # =========================================================================== #
14
- # require 'multimedia_paradise/audio/waveform/log.rb'
15
- # =========================================================================== #
16
- module MultimediaParadise
17
-
18
- class Waveform < ::MultimediaParadise::Base
19
-
20
- class Log # === MultimediaParadise::Waveform::Log
21
-
22
- attr_accessor :io
23
-
24
- # ========================================================================= #
25
- # === initialize
26
- # ========================================================================= #
27
- def initialize(io = $stdout)
28
- @io = io
29
- end
30
-
31
- # ========================================================================= #
32
- # === out
33
- #
34
- # Prints the given message to the log.
35
- # ========================================================================= #
36
- def out(i)
37
- io.print(i) if io
38
- end
39
-
40
- # ========================================================================= #
41
- # === done!
42
- #
43
- # Prints the given message to the log followed by the most recent
44
- # benchmark (note that it calls .end! which will stop the benchmark)
45
- # ========================================================================= #
46
- def done!(message = '')
47
- out "#{message} (#{self.end!}s)\n"
48
- end
49
-
50
- # ========================================================================= #
51
- # === start!
52
- #
53
- # Starts a new benchmark clock and returns the index of the new clock.
54
- #
55
- # If .start! is called again before .end! then the time returned will
56
- # be the elapsed time from the next call to start!, and calling .end!
57
- # again will return the time from *this* call to start! (that is, the
58
- # clocks are LIFO).
59
- # ========================================================================= #
60
- def start!
61
- (@benchmarks ||= []) << Time.now
62
- @current = @benchmarks.size - 1
63
- end
64
-
65
- # ========================================================================= #
66
- # === end!
67
- #
68
- # Returns the elapsed time from the most recently started benchmark clock
69
- # and ends the benchmark, so that a subsequent call to .end! will return
70
- # the elapsed time from the previously started benchmark clock.
71
- # ========================================================================= #
72
- def end!
73
- elapsed = (Time.now - @benchmarks[@current])
74
- @current -= 1
75
- elapsed
76
- end
77
-
78
- # ========================================================================= #
79
- # === time?
80
- #
81
- # Returns the elapsed time from the benchmark clock w/ the given index
82
- # (as returned from when .start! was called).
83
- # ========================================================================= #
84
- def time?(index)
85
- Time.now - @benchmarks[index]
86
- end
87
-
88
- # ========================================================================= #
89
- # === timed
90
- #
91
- # Benchmarks the given block, printing out the given message first
92
- # (if given).
93
- # ========================================================================= #
94
- def timed(message = nil, &block)
95
- start!
96
- out(message) if message
97
- yield
98
- done!
99
- end
100
-
101
- end; end; end
@@ -1,19 +0,0 @@
1
- #!/usr/bin/ruby -w
2
- # Encoding: UTF-8
3
- # frozen_string_literal: true
4
- # =========================================================================== #
5
- # require 'multimedia_paradise/base/constants.rb'
6
- # =========================================================================== #
7
- module MultimediaParadise
8
-
9
- class Base # === MultimediaParadise::Base
10
-
11
- require 'multimedia_paradise/constants/my_video_directory.rb'
12
- require 'multimedia_paradise/constants/directory_constants.rb'
13
-
14
- # ========================================================================= #
15
- # === N
16
- # ========================================================================= #
17
- N = "\n"
18
-
19
- end; end
@@ -1,31 +0,0 @@
1
- #!/usr/bin/ruby -w
2
- # Encoding: UTF-8
3
- # frozen_string_literal: true
4
- # =========================================================================== #
5
- # Encoding-related code should be stored in this file here.
6
- # =========================================================================== #
7
- module MultimediaParadise
8
-
9
- class Base
10
-
11
- require 'multimedia_paradise/constants/encodings.rb'
12
-
13
- # ========================================================================= #
14
- # === ensure_main_encoding
15
- #
16
- # This method can ensure that a String has the proper encoding that
17
- # we will use for the MultimediaParadise project.
18
- # ========================================================================= #
19
- def ensure_main_encoding(
20
- i, use_this_encoding = USE_THIS_ENCODING
21
- )
22
- if i.is_a? String
23
- unless i.encoding.to_s.include? use_this_encoding
24
- i = i.dup if i.frozen?
25
- i = i.force_encoding(use_this_encoding)
26
- end
27
- end
28
- i
29
- end
30
-
31
- end; end