TokyoR 64 LT
Rからmidiファイルを読んで
plotしてみたお話

niszet

2017/08/26

自己紹介

こんな人です

名前:niszet
R歴:約1年
趣味:R、楽器(お休み中)、ラズパイ
self

普段は回路設計などをして生きてます

raw型とは…

Rのデータ型(mode)いろいろ

  • integer
  • numeric
  • logical
  • factor
  • character
  • raw (今回紹介)
  • complex (機会があれば)

raw型=バイト型

  • 1つの要素で 1byte = 8bit = 2**8 = 0-255 までを表すことが出来る
  • バイナリファイル(データ)を扱う場合に使用する

  • complexと共に大体のRの書籍では紹介されない影の存在
  • as.raw() で0-255の整数を与えると作れる

rawはRのmodeの中でも最弱…

c("a", as.raw(1)); c(1.0+1.0i, as.raw(1)); 
## [1] "a"  "01"
## [1] 1+1i 1+0i
c(1.0, as.raw(1)); c(TRUE, as.raw(1));
## [1] 1 1
## [1] TRUE TRUE
  • NULLなら勝てそう(NAはlogicalなので負ける)

operatorはほとんど使えない

  • 加減乗除は使用できない
# as.raw(1)+as.raw(1)
## Error in as.raw(1) + as.raw(1) : 
##    non-numeric argument to binary operator
  • 比較はできる
as.raw(1)<as.raw(2)
## [1] TRUE

bit単位のand, or演算が出来る

raw型に対しては&|はbit単位でのAnd/Orをとる演算子となる。

# 0011_1100(0x3c) & 0110_0110(0x66) = 0010_0100(0x24)
as.raw(60) & as.raw(102)
## [1] 24
# 0011_1100(0x3c) & 0110_0110(0x66) = 0111_1110(0x7e)
as.raw(60) | as.raw(102)
## [1] 7e

ベクトル化も可能

c(as.raw(12),as.raw(255)) & c(as.raw(255),as.raw(1))
## [1] 0c 01

関連する関数

  • ファイルから(正確にはconnectionから)値を読む
    • readBin
      • readChar(asciiの場合)
    • scan
  • ファイルに値を書く
    • writeBin
      • writeChar(asciiの場合)

大体の場合はas.raw()as.integer()で相互に型を変換して使うことになるかと思います 使い方はヘルプを参照ください(一番詳しい資料はヘルプ)

midiファイルを読んでみる

ライブラリを自作してみる

読んでみる

# rsmf型として一旦ファイルを読む
smf <- read_smf("midi/AveMaria.mid")
# rsmf型から音の高さやなる時間などを抜き出してdata.frameに変換。
nf <- make_note_frame(smf)
# データの中身
head(nf, n=4)
##   ch height val start_time end_time nn
## 2  0     53  30          0       48  5
## 3  0     57  30         48       96  9
## 4  0     60  30         96      144  0
## 5  0     65  30        144      192  5

read_smfの中身

# read_smfの中身
head(read_smf)
##                                             
## 1 function (file)                           
## 2 {                                         
## 3     con <- file(file, "rb")               
## 4     on.exit(close(con))                   
## 5     file_size <- file.info(file)[["size"]]
## 6     smf_header <- read_header(con)
# その中でreadBinを使用しています
head(rmusicwork:::read_track_data_size)
##                                                                        
## 1 function (con)                                                       
## 2 {                                                                    
## 3     tds <- readBin(con, "integer", n = 1L, size = 4L, endian = "big")
## 4     tds                                                              
## 5 }

plotしてみる

# geom_segment で始点と終点になる列を指定。はじめの1/3だけplot
nf %>% ggplot()+geom_segment(aes(
  x=start_time, y=height, xend=end_time,yend=height,
  color=as.factor(nn), size=1)) + xlim(c(0,10000))+
  xlab("time") + ylab("height") + theme(legend.position="none")+
  scale_colour_brewer(palette = "Paired")

まとめ

まとめ

  • やったこと
    • Rの関数だけでバイナリファイルを扱えることを確認した。
    • midiファイルを読むためのパッケージを作成しplot出来るようにした。
  • 課題
    • ファイルの読み込みが遅い(可変長データのため。RCpp化する?)
    • data.frameからmidiファイルへ出力したい(SMFの理解が足りない)
      • 色々なデータセットから音を出せるようにしたい

ありがとうぞうさん

zousan

Enjoy!!

self