#
# パワー抽出用スレッド
#

#------------------------------------------------------
package require -exact snack 2.2
package require Thread

#------------------------------------------------------
# 大域変数
array unset power
set power(mutex) [::thread::mutex create]   ;# mutex
set power(mainID) [tsv::get tid main]  ;# メインスレッドのID
set power(fname) ""                         ;# power抽出したwavファイル名
set power(mtimeSec) 0                       ;# power抽出したwavファイルの更新時刻

#------------------------------------------------------
# powerを抽出する
# force=1...抽出オプションを変更したときに強制的に再抽出させる
#
proc getPower {fname inWavMtimeSec {force 0}} {
  global power

  ;# 排他制御用にロックをかける
  ::thread::mutex lock $power(mutex)

  ;# 以前power抽出したファイルと同じファイルであれば終了
  if {!$force && $fname == $power(fname) && $inWavMtimeSec == $power(mtimeSec)} {
    ::thread::mutex unlock $power(mutex)
    return
  }

  ;# power結果を初期化
  tsv::set power power {}
  tsv::set power status 1     ;# 1=抽出中

  ;# 抽出用パラメータを得る
  foreach key {frameLength window preemphasis windowLength sampleRate} {
    set power($key) [tsv::get power $key]
  }
  snack::sound sWork

  ;# wavファイルを読み込み、モノラル化や正規化を行う
  if {![file readable $fname]} {
    ::thread::mutex unlock $power(mutex)
    return
  }
  sWork read $fname

  ;# パワーを抽出
  set series [sWork power -framelength $power(frameLength) \
      -windowtype $power(window) -preemphasisfactor $power(preemphasis) \
      -windowlength [expr int($power(windowLength) * $power(sampleRate))] \
      -start 0 -end -1]

  ;# 描画用のパラメータをいくつか求める
  if {[llength $series] > 0} {
    # パワーの最大値・最小値を求める
    set power(powerMax) [lindex $series 0]
    set power(powerMin) [lindex $series 0]
    for {set i 1} {$i < [llength $series]} {incr i} {
      if {$power(powerMax) < [lindex $series $i]} {
        set power(powerMax) [lindex $series $i]
      }
      if {$power(powerMin) > [lindex $series $i]} {
        set power(powerMin) [lindex $series $i]
      }
    }
    if {$power(powerMin) < 0} { set power(powerMin) 0 }
  }

  ;# 結果を返す＆記録する
  set power(fname)    $fname
  set power(mtimeSec) $inWavMtimeSec  ;# power抽出対象のwavの更新日付を記録
  foreach key {powerMax powerMin} {
    tsv::set power $key $power($key)
  }
  tsv::set power power $series
  tsv::set power status 0       ;# 抽出が終わったので0にする

  ;# 描画する
  ::thread::send $power(mainID) [list Redraw power]

  ;# ロックを外す
  ::thread::mutex unlock $power(mutex)
}

