それで困るのは非常に1曲が長いCDの場合だ。
例えば、極端な例だが、「セイシェル」は1CD1トラック。1曲(?)が57分ある。
普通は冒頭部分を少し聴いてスキップすることになる。
ただそれだと後半部などは一生聴くことがない。
そこで長いトラックを再生しようとした時、その曲のある部分だけ選択して再生するよう提案してくれるスクリプトをHaskellで書いてみた。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import System.Random | |
toD :: IO Double | |
toD = do | |
putStrLn $ "分 秒" | |
r <- getLine | |
let a:b:_ = words r | |
return $ (read a * 60) + read b | |
f d n = do | |
let t = d / n | |
if t < 300 | |
then return n | |
else f d (n + 1) | |
f2 d n = | |
map (\x -> (x*d,x*d+d)) [0..(n - 1)] | |
disp (a,b) = do | |
print ((round a `div` 60, round a `mod` 60), (round b `div` 60, round b `mod` 60)) | |
main = do | |
r <- toD | |
print r | |
n <- f r 2 | |
print n | |
print $ r / n | |
let l = f2 (r / n) n | |
print l | |
rand <- (getStdRandom $ randomR (0,round (n - 1)) :: IO Int) | |
print $ l !! rand | |
disp $ l !! rand |
$ runghc m2.hs
分 秒
57 42
3462.0
12.0
288.5
[(0.0,288.5),(288.5,577.0),(577.0,865.5),(865.5,1154.0),(1154.0,1442.5),(1442.5,1731.0),(1731.0,2019.5),(2019.5,2308.0),(2308.0,2596.5),(2596.5,2885.0),(2885.0,3173.5),(3173.5,3462.0)]
(0.0,288.5)
(0,0),(4,49)
「セイシェル」のケース。
トラックの演奏時間が、3462秒。
12分割すると
1単位が288秒。
その場合の各サブトラックがタプルのリストで表示されている。
そこからランダムに選びスクリプトが提案したのが
(0,0),(4,49)
つまり冒頭から4分49秒まで。
また別の機会では、
(38,29),(43,17)
つまり38分29秒から43分17秒まで。
これなら1回5分程度の演奏で済み、やがては、まんべんなく全曲を聴くことができるはずだ。(長い目でみれば)
スクリプトは高度なアルゴリズムなどは使っておらず、適当に分割してリストの要素をランダムに選択しているだけです。
なおあるトラックの演奏時間は「Soxi」コマンドにDオプションをつければ取得できます。
$ soxi -D ~/music/Seychelles/Seychelles/sdem.flac
3462.866667
$ soxi -d ~/music/Seychelles/Seychelles/sdem.flac
00:57:42.87
実際に使ってみると演奏を中断してスクリプトを実行する、というのはとても面倒だった。
実際に使ってみると演奏を中断してスクリプトを実行する、というのはとても面倒だった。
で予め適当な長さに分割しておくことにした。
本当はプレイリストなどから、自動で分割してまわるようにするといいのかもしれないが、
残念ながらそこまでの知識はないので、一つ一つ手作業で分割する。
まず適当なディレクトリー(tmp)をつくって目的のファイルをコピーしておく。
このディレクトリーには各種スクリプトがすでに存在するものとする。
a.hs
m.hs
の2つ。
$ ls tmp
a.hs m.hs sdem.flac
実行例
$ runghc a.hs sdem.flac | runghc m.hs
確かにFlacファイルが12分割されている。
なお1から11までのサブトラックと最後のサブトラックの処理をわけているのは、
元のトラックの長さを超えて時間指定すると、Soxがエラーになるためです。
気にしなければ必要ありません。
前後に無音部分を挿入したり、フェードイン、フェードアウトしたり色々できるとは思いますが、
そのへんは演奏ソフトに任せたほうが得策かも・・・
Soxコマンドには分割のためのオプションも存在しますが、曲の途中でぶつ切りしてしまいます。
Haskellのスクリプトでは10秒分クロスするようにしています。
Gui版
https://github.com/index333/trim
本当はプレイリストなどから、自動で分割してまわるようにするといいのかもしれないが、
残念ながらそこまでの知識はないので、一つ一つ手作業で分割する。
まず適当なディレクトリー(tmp)をつくって目的のファイルをコピーしておく。
このディレクトリーには各種スクリプトがすでに存在するものとする。
a.hs
m.hs
の2つ。
$ ls tmp
a.hs m.hs sdem.flac
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import System.Environment | |
import System.Process | |
main = do | |
[a] <- getArgs | |
putStrLn a |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import System.FilePath.Posix | |
import System.Process | |
getC :: IO (String, Double) | |
getC = do | |
c <- getContents | |
let a:b:_ = lines c | |
return (a, read b) | |
f d n = do | |
let t = d / n | |
if t < 300 | |
then return n | |
else f d (n + 1) | |
f2 d n = map (\x -> x*d) [0..(n - 1)] | |
doComs f d l = do | |
print f | |
print $ takeBaseName f | |
print d | |
mapM_ (\x -> do | |
putStr f | |
putStr " -> " | |
putStrLn $ nf f x) l | |
mapM_ (\x -> do | |
createProcess (proc "sox" [f,nf f x,"trim" ,show x , show (d+10)]) >> return ()) (init l) | |
let lst = last l | |
createProcess (proc "sox" [f,nf f lst,"trim" ,show lst]) >> return () | |
nf f x = "trimed" ++ show (round x) ++ takeBaseName f ++ ".flac" | |
main = do | |
(a,b) <- getC | |
print (a,b) | |
n <- f b 2 | |
print n | |
let d = b / n | |
print d | |
let l = f2 d n | |
print l | |
doComs a d l |
実行例
$ runghc a.hs sdem.flac | runghc m.hs
("sdem.flac",3462.866667)
12.0
288.57222225
[0.0,288.57222225,577.1444445,865.71666675,1154.288889,1442.8611112499998,1731.4333335,2020.00555575,2308.577778,2597.1500002499997,2885.7222224999996,3174.29444475]
"sdem.flac"
288.57222225
sdem.flac -> trimed0sdem.flac
sdem.flac -> trimed289sdem.flac
sdem.flac -> trimed577sdem.flac
sdem.flac -> trimed866sdem.flac
sdem.flac -> trimed1154sdem.flac
sdem.flac -> trimed1443sdem.flac
sdem.flac -> trimed1731sdem.flac
sdem.flac -> trimed2020sdem.flac
sdem.flac -> trimed2309sdem.flac
sdem.flac -> trimed2597sdem.flac
sdem.flac -> trimed2886sdem.flac
sdem.flac -> trimed0sdem.flac
sdem.flac -> trimed289sdem.flac
sdem.flac -> trimed577sdem.flac
sdem.flac -> trimed866sdem.flac
sdem.flac -> trimed1154sdem.flac
sdem.flac -> trimed1443sdem.flac
sdem.flac -> trimed1731sdem.flac
sdem.flac -> trimed2020sdem.flac
sdem.flac -> trimed2309sdem.flac
sdem.flac -> trimed2597sdem.flac
sdem.flac -> trimed2886sdem.flac
$ ls -hl
合計 559M
-rw-rw-r-- 1 i i 147 2月 21 09:43 a.hs
-rw-rw-r-- 1 i i 882 2月 22 05:13 m.hs
-rwxrwxr-x 1 i i 276M 2月 22 05:11 sdem.flac
-rw-rw-r-- 1 i i 27M 2月 22 05:14 trimed0sdem.flac
-rw-rw-r-- 1 i i 23M 2月 22 05:14 trimed1154sdem.flac
-rw-rw-r-- 1 i i 23M 2月 22 05:14 trimed1443sdem.flac
-rw-rw-r-- 1 i i 22M 2月 22 05:14 trimed1731sdem.flac
-rw-rw-r-- 1 i i 23M 2月 22 05:14 trimed2020sdem.flac
-rw-rw-r-- 1 i i 24M 2月 22 05:14 trimed2309sdem.flac
-rw-rw-r-- 1 i i 24M 2月 22 05:14 trimed2597sdem.flac
-rw-rw-r-- 1 i i 25M 2月 22 05:14 trimed2886sdem.flac
-rw-rw-r-- 1 i i 26M 2月 22 05:14 trimed289sdem.flac
-rw-rw-r-- 1 i i 22M 2月 22 05:14 trimed3174sdem.flac
-rw-rw-r-- 1 i i 26M 2月 22 05:14 trimed577sdem.flac
-rw-rw-r-- 1 i i 25M 2月 22 05:14 trimed866sdem.flac
$ soxi -d *flac
00:57:42.87
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:58.57
00:04:48.57
00:04:58.57
00:04:58.57
なお1から11までのサブトラックと最後のサブトラックの処理をわけているのは、
元のトラックの長さを超えて時間指定すると、Soxがエラーになるためです。
気にしなければ必要ありません。
前後に無音部分を挿入したり、フェードイン、フェードアウトしたり色々できるとは思いますが、
そのへんは演奏ソフトに任せたほうが得策かも・・・
Soxコマンドには分割のためのオプションも存在しますが、曲の途中でぶつ切りしてしまいます。
Haskellのスクリプトでは10秒分クロスするようにしています。
Gui版
https://github.com/index333/trim
すべてのHaskellスクリプトはホームディレクトリーに置くことにした。
trim というスクリプトを用意している。
$ cat trim
runghc ~/fc.hs > fn
runghc ~/t.hs | runghc ~/t2.hs
runghc ~/del.hs
ひと工夫必要だった。
まずファイル・チューザー・ダイアログの設定ファイル
~/.config/gtk-2.0/gtkfilechooser.ini
を編集する。
$ cat ~/.config/gtk-2.0/gtkfilechooser.ini
[Filechooser Settings]
LocationMode=path-bar
ShowHidden=false
ShowSizeColumn=true
GeometryX=0
GeometryY=0
GeometryWidth=720
GeometryHeight=540
SortColumn=name
SortOrder=ascending
StartupMode=recent
StartupModeがrecentとなっているのをcwd(current-working-directory) に書き換える。
StartupMode=cwd
次にファイルマネージャーで分割したいFlacファイルのあるディレクトリーを探し
そのディレクトリーで端末を開く。
Mateのファイルマネージャー「Caja」の場合
「端末の中に開く」をクリック。
このように端末が開くので、このディレクトリーからスクリプトを起動する。
なおスクリプト「trim」は、実行権限を与えておく。
$ chmod 777 trim
またTrisquelではあらかじめ$HOME/binに実行パスが通っているので
bin ディレクトリーを作ってコピーしておけばよい。
$ mkdir bin
$ cp trim bin
$ ll bin
合計 4.0K
-rwxrwxr-x 1 i i 67 3月 12 12:36 trim
実行例
ファイル・チューザー・ダイアログが開くので目的のFlacファイルを選択すればSoxコマンドにより適当に分割してくれる。
同ディレクトリー内の他のファイルも分割したければ、再度スクリプトを起動すればよい。
注:Soxコマンドはイメージタグ等の編集はできないので、分割で作られた新たなFlacファイルには
EasyTag等で手動でタグ付けが必要です。
0 件のコメント:
コメントを投稿