1#!/bin/sh 2# the next line restarts using wish \ 3exec wish8.4 "$0" "$@" 4 5package require -exact snack 2.2 6# Try to load optional file format handlers 7catch { package require snacksphere } 8catch { package require snackogg } 9package require http 10 11set debug 0 12snack::debug $debug 13snack::sound snd -debug $debug 14snack::sound cbs -debug $debug 15 16set tcl_precision 7 17set f(prog) [info script] 18set f(labfile) "" 19set f(sndfile) "" 20set f(lpath) "" 21set f(header) "" 22set mexhome "~/snack/" 23catch {source $mexhome/ipa_tmh.tcl} 24set f(ipapath) $mexhome/ipa_xbm 25set local 0 26if $local { 27 set v(labfmt) TIMIT 28 set v(smpfmt) WAV 29 set v(ashost) ior.speech.kth.se 30} else { 31 set v(labfmt) TIMIT 32 set v(smpfmt) WAV 33 set v(ashost) localhost 34} 35set labels {} 36set undo {} 37set v(labchanged) 0 38set v(smpchanged) 0 39set v(width) 600 40set v(toth) 286 41set v(msg) "Press right mouse button for menu" 42set v(timeh) 20 43set v(yaxisw) 40 44set v(labelh) 20 45set v(psfilet) {tmp$N.ps} 46set v(psfile) "" 47set v(vchan) -1 48#set v(offset) 0 49#set v(zerolabs) 0 50set v(startsmp) 0 51set v(lastmoved) -1 52set v(p_version) 2.2 53set v(s_version) 2.2 54set v(plugins) {} 55set v(scroll) 1 56set v(rate) 16000 57set v(sfmt) Lin16 58set v(chan) 1 59set v(topfr) 8000 60set v(rp_sock) "" 61#set v(propflag) 0 62set v(pause) 0 63set v(recording) 1 64set v(activerec) 0 65set v(cmap) grey 66set v(grey) " " 67#set v(color1) {#000 #006 #00B #00F #03F #07F #0BF #0FF #0FB #0F7 \ 68 #0F0 #3F0 #7F0 #BF0 #FF0 #FB0 #F70 #F30 #F00} 69set v(color1) {#000 #004 #006 #00A #00F \ 70 #02F #04F #06F #08F #0AF #0CF #0FF #0FE \ 71 #0FC #0FA #0F8 #0F6 #0F4 #0F2 #0F0 #2F0 \ 72 #4F0 #6F0 #8F0 #AF0 #CF0 #FE0 #FC0 #FA0 \ 73 #F80 #F60 #F40 #F20 #F00} 74set v(color2) {#FFF #BBF #77F #33F #00F #07F #0BF #0FF #0FB #0F7 \ 75 #0F0 #3F0 #7F0 #BF0 #FF0 #FB0 #F70 #F30 #F00} 76set v(contrast) 0 77set v(brightness) 0 78set v(showspeg) 0 79set v(remspegh) 200 80set v(remote) 0 81set v(asport) 23654 82set v(handle) "" 83set v(s0) 0 84 85set z(zoomwinh) 200 86set z(zoomwinw) 600 87set z(zoomwinx) 200 88set z(zoomwiny) 200 89set z(zoomwavh) 0 90set z(zoomwavw) 0 91set z(f) 1 92 93set s(sectwinh) 400 94set s(sectwinw) 400 95set s(sectwinx) 200 96set s(sectwiny) 200 97set s(secth) 400 98set s(sectw) 400 99set s(rx) -1 100 101proc SetDefaultVars {} { 102 global f v s local 103 104 set v(waveh) 50 105 set v(spegh) 0 106 set v(scrw) 32767 107 set v(pps) 400 108 set v(opps) 400 109 set v(fftlen) 256 110 set v(winlen) 128 111 set v(anabw) 125 112 set v(preemph) 0.97 113 set v(ipa) 0 114 set v(autoload) 0 115 set v(ch) 0 116 set v(slink) 0 117 set v(mlink) 0 118 if {$::tcl_platform(platform) == "unix"} { 119 set v(printcmd) {lpr $FILE} 120 set v(gvcmd) {ghostview $FILE} 121 set v(psfilecmd) {cp -f _xspr$n.ps $v(psfile)} 122 if $local { 123 set v(pluginfiles) {~/snack/xsplug/dataplot.plg ~/snack/xsplug/generator.plg ~/snack/xsplug/transcribe.plg ~/snack/xsplug/cutter.plg ~/snack/xsplug/pitch.plg} 124 } else { 125 set v(pluginfiles) [glob -nocomplain *.plg] 126 } 127# set v(browser) "netscape" 128 if {$::tcl_platform(os) == "HP-UX"} { 129 option add *font {Helvetica 10 bold} 130 } else { 131 option add *font {Helvetica 12 bold} 132 } 133 } else { 134 set v(printcmd) {C:/gs/gs6.50/bin/gswin32 "-IC:\gs\gs6.50;C:\gs\gs6.50\fonts" -sDEVICE=laserjet -dNOPAUSE $FILE -c quit} 135 set v(gvcmd) {C:/ghostgum/gsview/gsview32 $FILE} 136 set v(psfilecmd) {command.com /c copy _xspr$n.ps $v(psfile)} 137 if $local { 138# set v(pluginfiles) {H:/tcl/mexd/dataplot.plg H:/tcl/mexd/generator.plg H:/tcl/mexd/pitch.plg} 139 set v(pluginfiles) {} 140 } else { 141 set v(pluginfiles) [glob -nocomplain *.plg] 142 } 143# set v(browser) "c:/program files/netscape/communicator/program/netscape.exe" 144 } 145 set v(ipafmt) TMH 146 set v(labalign) w 147 set v(fg) black 148 set v(bg) [. cget -bg] 149 if {[string match macintosh $::tcl_platform(platform)] || \ 150 [string match Darwin $::tcl_platform(os)]} { 151 set v(fillmark) 0 152 } else { 153 set v(fillmark) 1 154 } 155 set v(font) {Courier 10} 156 if {[string match unix $::tcl_platform(platform)] } { 157 set v(sfont) {Helvetica 10 bold} 158 } else { 159 set v(sfont) {Helvetica 8 bold} 160 } 161 set v(gridfspacing) 0 162 set v(gridtspacing) 0 163 set v(gridcolor) red 164 set v(cmap) grey 165 set v(showspeg) 0 166 set v(remspegh) 200 167 set v(linkfile) 0 168 set f(skip) 0 169 set f(byteOrder) "" 170 set f(ipath) "" 171 set f(ihttp) "http://www.speech.kth.se/~kare/ex1.wav" 172 #"http://www.speech.kth.se/cgi-bin/TransAll?this_is_an_example+am" 173 174 set s(fftlen) 512 175 set s(anabw) 31.25 176 set s(ref) -110.0 177 set s(range) 110.0 178 set s(wintype) Hamming 179 set s(atype) FFT 180 set s(lpcorder) 20 181 182 if {[info exists snack::snackogg]} { 183 set ::ogg(nombr) 128000 184 set ::ogg(maxbr) -1 185 set ::ogg(minbr) -1 186 set ::ogg(com) "" 187 set ::ogg(query) 1 188 } 189} 190 191SetDefaultVars 192catch { source [file join ~ .xsrc] } 193catch { source [file join ~ .xsrf] } 194 195snd config -rate $v(rate) 196snd config -encoding $v(sfmt) 197snd config -channels $v(chan) 198 199set filt(f) [snack::filter map 0.0] 200 201set echo(f) [snack::filter echo 0.6 0.6 30 0.4] 202set echo(n) 1 203set echo(drain) 1 204set echo(iGain) 60 205set echo(oGain) 60 206 207set mix(f) [snack::filter map 0.0] 208 209set amplify(f) [snack::filter map 1.0] 210set amplify(v) 100.0 211set amplify(db) 0 212 213set normalize(f) [snack::filter map 1.0] 214set normalize(v) 100.0 215set normalize(db) 0 216set normalize(allEqual) 1 217 218set remdc(f) [snack::filter iir -numerator "0.99 -0.99" -denominator "1 -0.99"] 219 220set f(spath) $f(ipath) 221set f(http) $f(ihttp) 222set f(urlToken) "" 223 224if {$v(p_version) != $v(s_version)} { 225 set v(msg) "Warning, you have saved settings from an older version of xs!" 226 SetDefaultVars 227} 228 229# Put custom settings between the lines below 230# Custom settings start here 231# Custom settings end here 232 233snack::menuInit 234snack::menuPane File 235snack::menuCommand File {Open...} GetOpenFileName 236snack::menuBind . o File {Open...} 237snack::menuCommand File {Get URL...} OpenGetURLWindow 238snack::menuCommand File Save Save 239snack::menuBind . s File Save 240snack::menuCommand File {Save As...} SaveAs 241snack::menuCommand File Close Close 242snack::menuSeparator File 243snack::menuCommand File Print... {Print .cf.fc.c -1} 244snack::menuCommand File Info {set v(msg) [InfoStr nopath]} 245snack::menuSeparator File 246if [info exists recentFiles] { 247 foreach e $recentFiles { 248 snack::menuCommand File $e [list OpenFiles $e] 249 } 250 snack::menuSeparator File 251} 252snack::menuCommand File Exit Exit 253 254snack::menuPane Edit 0 ConfigEditMenu 255snack::menuCommand Edit Undo Undo 256snack::menuEntryOff Edit Undo 257snack::menuSeparator Edit 258snack::menuCommand Edit Cut Cut 259snack::menuBind . x Edit Cut 260snack::menuCommand Edit Copy Copy 261snack::menuBind . c Edit Copy 262snack::menuCommand Edit Paste Paste 263snack::menuBind . v Edit Paste 264snack::menuCommand Edit Crop Crop 265snack::menuCommand Edit {Mark All} MarkAll 266snack::menuCommand Edit {Zero Cross Adjust} ZeroXAdjust 267 268set n [snack::menuPane Audio] 269bind $n <<MenuSelect>> { snack::mixer update } 270snack::menuCommand Audio {Play range} PlayMark 271snack::menuCommand Audio {Play All} PlayAll 272snack::menuBind . p Audio {Play All} 273snack::menuCommand Audio {Stop Play} StopPlay 274#snack::menuCommand Audio {Gain Control...} {snack::gainBox rp} 275snack::menuCommand Audio Mixer... snack::mixerDialog 276#if {[snack::mixer inputs] != ""} { 277# snack::menuCascade Audio Input 278# foreach jack [snack::mixer inputs] { 279# snack::mixer input $jack v(in$jack) 280# snack::menuCheck Input $jack v(in$jack) 281# } 282#} 283#if {[snack::mixer outputs] != ""} { 284# snack::menuCascade Audio Output 285# foreach jack [snack::mixer outputs] { 286# snack::mixer output $jack v(out$jack) 287# snack::menuCheck Output $jack v(out$jack) 288# } 289#} 290snack::menuCascade Audio {Audio Settings} 291snack::menuCascade {Audio Settings} {Set Sample Rate} 292set rateList [snack::audio rates] 293if {$rateList == ""} { 294 set rateList {11025 22050 44100} 295} 296foreach fr $rateList { 297 snack::menuRadio {Set Sample Rate} $fr v(rate) $fr SetRaw 298} 299snack::menuCascade {Audio Settings} {Set Encoding} 300foreach fo [snack::audio encodings] { 301 snack::menuRadio {Set Encoding} $fo v(sfmt) $fo SetRaw 302} 303snack::menuCascade {Audio Settings} {Set Channels} 304snack::menuRadio {Set Channels} Mono v(chan) 1 SetRaw 305snack::menuRadio {Set Channels} Stereo v(chan) 2 SetRaw 306 307snack::menuPane Transform 0 ConfigTransformMenu 308snack::menuCascade Transform Conversions 309snack::menuCascade Conversions {Convert Sample Rate} 310foreach fr $rateList { 311 snack::menuCommand {Convert Sample Rate} $fr "Convert {} $fr {}" 312} 313snack::menuCascade Conversions {Convert Encoding} 314foreach fo [snack::audio encodings] { 315 snack::menuCommand {Convert Encoding} $fo "Convert $fo {} {}" 316} 317snack::menuCascade Conversions {Convert Channels} 318snack::menuCommand {Convert Channels} Mono "Convert {} {} Mono" 319snack::menuCommand {Convert Channels} Stereo "Convert {} {} Stereo" 320snack::menuCommand Transform Amplify... Amplify 321snack::menuCommand Transform Normalize... Normalize 322#snack::menuCommand Transform Normalize... Normalize 323snack::menuCommand Transform Echo... Echo 324snack::menuCommand Transform {Mix Channels...} MixChan 325snack::menuCommand Transform Invert Invert 326snack::menuCommand Transform Reverse Reverse 327snack::menuCommand Transform Silence Silence 328snack::menuCommand Transform {Remove DC} RemoveDC 329 330snack::menuPane Tools 331 332snack::menuPane Options 0 ConfigOptionsMenu 333snack::menuCommand Options Settings... Settings 334if {[info exists snack::snackogg]} { 335 snack::menuCommand Options "Ogg Vorbis..." [list OggSettings Close] 336} 337snack::menuCommand Options Plug-ins... Plugins 338snack::menuCascade Options {Label File Format} 339snack::menuRadio {Label File Format} TIMIT v(labfmt) TIMIT {Redraw quick} 340snack::menuRadio {Label File Format} HTK v(labfmt) HTK {Redraw quick} 341snack::menuRadio {Label File Format} WAVES v(labfmt) WAVES {Redraw quick} 342snack::menuRadio {Label File Format} MIX v(labfmt) MIX {Redraw quick} 343if $local { 344 snack::menuCascade Options {IPA Translation} 345 snack::menuRadio {IPA Translation} TMH v(ipafmt) TMH {source $mexhome/ipa_tmh.tcl;Redraw quick} 346 snack::menuRadio {IPA Translation} CMU v(ipafmt) CMU {source $mexhome/ipa_cmu.tcl;Redraw quick} 347} 348snack::menuCascade Options {Label Alignment} 349snack::menuRadio {Label Alignment} left v(labalign) w {Redraw quick} 350snack::menuRadio {Label Alignment} center v(labalign) c {Redraw quick} 351snack::menuRadio {Label Alignment} right v(labalign) e {Redraw quick} 352snack::menuCascade Options {View Channel} 353snack::menuRadio {View Channel} both v(vchan) -1 { Redraw;DrawZoom 1;DrawSect } 354snack::menuRadio {View Channel} left v(vchan) 0 { Redraw;DrawZoom 1;DrawSect } 355snack::menuRadio {View Channel} right v(vchan) 1 { Redraw;DrawZoom 1;DrawSect } 356snack::menuSeparator Options 357if $local { 358 snack::menuCheck Options {IPA Transcription} v(ipa) {Redraw quick} 359} 360snack::menuCheck Options {Record Button} v(recording) ToggleRecording 361snack::menuCheck Options {Show Spectrogram} v(showspeg) ToggleSpeg 362snack::menuCheck Options {Auto Load} v(autoload) 363snack::menuCheck Options {Cross Hairs} v(ch) DrawCrossHairs 364snack::menuCheck Options {Fill Between Marks} v(fillmark) {$c coords mfill -1 -1 -1 -1 ; Redraw quick} 365snack::menuCheck Options {Link to Disk File} v(linkfile) Link2File 366if {$tcl_platform(platform) == "unix"} { 367 snack::menuCheck Options {Link Scroll} v(slink) 368 snack::menuCheck Options {Link Marks} v(mlink) 369} 370#snack::menuCheck Options {Align x-axis/first label} v(offset) {Redraw quick} 371#snack::menuCheck Options {Show zero length labels} v(zerolabs) {Redraw quick} 372snack::menuSeparator Options 373snack::menuCommand Options {Set default options} {SetDefaultVars ; Redraw} 374snack::menuCommand Options {Save options} SaveSettings 375 376snack::menuPane Window 377snack::menuCommand Window {New Window} NewWin 378snack::menuBind . n Window {New Window} 379snack::menuCommand Window Refresh Redraw 380snack::menuBind . r Window Refresh 381snack::menuCommand Window {Waveform Zoom} OpenZoomWindow 382snack::menuCommand Window {Spectrum Section} OpenSectWindow 383#snack::menuCommand Window {WaveSurfer} WS 384 385snack::menuPane Help 386snack::menuCommand Help Version Version 387snack::menuCommand Help Manual {Help http://www.speech.kth.se/snack/xs.html} 388 389# Put custom menus between the lines below 390# Custom menus start here 391# Custom menus end here 392 393#bind Menu <<MenuSelect>> { 394# global v 395# if {[catch {%W entrycget active -label} label]} { 396# set label "" 397# } 398# set v(msg) $label 399# update idletasks 400#} 401 402if {$tcl_platform(platform) == "windows"} { 403 set border 1 404} else { 405 set border 0 406} 407 408snack::createIcons 409pack [frame .tb -highlightthickness 1] -anchor w 410pack [button .tb.open -command GetOpenFileName -image snackOpen -highlightthickness 0 -border $border] -side left 411 412pack [button .tb.save -command Save -image snackSave -highlightthickness 0 -border $border] -side left 413pack [button .tb.print -command {Print .cf.fc.c -1} -image snackPrint -highlightthickness 0 -border $border] -side left 414 415pack [frame .tb.f1 -width 1 -height 20 -highlightth 1] -side left -padx 5 416pack [button .tb.cut -command Cut -image snackCut -highlightthickness 0 -border $border] -side left 417pack [button .tb.copy -command Copy -image snackCopy -highlightthickness 0 -border $border] -side left 418pack [button .tb.paste -command Paste -image snackPaste -highlightthickness 0 -border $border] -side left 419 420pack [frame .tb.f2 -width 1 -height 20 -highlightth 1] -side left -padx 5 421pack [button .tb.undo -command Undo -image snackUndo -highlightthickness 0 -border $border -state disabled] -side left 422 423pack [frame .tb.f3 -width 1 -height 20 -highlightth 1] -side left -padx 5 424pack [button .tb.play -command PlayMark -bitmap snackPlay -fg blue3 -highlightthickness 0 -border $border] -side left 425bind .tb.play <Enter> {SetMsg "Play mark"} 426pack [button .tb.pause -command PausePlay -bitmap snackPause -fg blue3 -highlightthickness 0 -border $border] -side left 427bind .tb.pause <Enter> {SetMsg "Pause"} 428pack [button .tb.stop -command StopPlay -bitmap snackStop -fg blue3 -highlightthickness 0 -border $border] -side left 429bind .tb.stop <Enter> {SetMsg "Stop"} 430pack [button .tb.rec -command Record -bitmap snackRecord -fg red -highlightthickness 0 -border $border] -side left 431bind .tb.rec <Enter> {SetMsg "Record"} 432#pack [button .tb.gain -command {snack::gainBox rp} -image snackGain -highlightthickness 0 -border $border] -side left 433pack [button .tb.gain -command snack::mixerDialog -image snackGain -highlightthickness 0 -border $border] -side left 434bind .tb.gain <Enter> {SetMsg "Open gain control panel"} 435 436pack [frame .tb.f4 -width 1 -height 20 -highlightth 1] -side left -padx 5 437pack [button .tb.zoom -command OpenZoomWindow -image snackZoom -highlightthickness 0 -border $border] -side left 438bind .tb.zoom <Enter> {SetMsg "Open zoom window"} 439 440frame .of 441pack [canvas .of.c -width $v(width) -height 30 -bg $v(bg)] -fill x -expand true 442pack [scrollbar .of.xscroll -orient horizontal -command ScrollCmd] -fill x -expand true 443bind .of.xscroll <ButtonPress-1> { set v(scroll) 1 } 444bind .of.xscroll <ButtonRelease-1> RePos 445bind .of.c <1> {OverPlay %x} 446 447pack [ frame .bf] -side bottom -fill x 448entry .bf.lab -textvar v(msg) -width 1 -relief sunken -bd 1 -state disabled 449pack .bf.lab -side left -expand yes -fill x 450 451set v(toth) [expr $v(waveh) + $v(spegh) + $v(timeh)+ $v(labelh)] 452pack [ frame .cf] -fill both -expand true 453pack [ frame .cf.fyc] -side left -anchor n 454canvas .cf.fyc.yc2 -height 0 -width $v(yaxisw) -highlightthickness 0 455pack [ canvas .cf.fyc.yc -width $v(yaxisw) -height $v(toth) -highlightthickness 0 -bg $v(bg)] 456 457pack [ frame .cf.fc] -side left -fill both -expand true 458set c [canvas .cf.fc.c -width $v(width) -height $v(toth) -xscrollcommand [list .cf.fc.xscroll set] -yscrollcommand [list .cf.fc.yscroll set] -closeenough 5 -highlightthickness 0 -bg $v(bg)] 459scrollbar .cf.fc.xscroll -orient horizontal -command [list $c xview] 460scrollbar .cf.fc.yscroll -orient vertical -command yScroll 461#pack .cf.fc.xscroll -side bottom -fill x 462#pack .cf.fc.yscroll -side right -fill y 463pack $c -side left -fill both -expand true 464 465proc yScroll {args} { 466 global c 467 468 eval .cf.fyc.yc yview $args 469 eval $c yview $args 470} 471 472$c create rect -1 -1 -1 -1 -tags mfill -fill yellow -stipple gray25 473$c create line -1 0 -1 $v(toth) -width 1 -tags [list mark [expr 0 * $v(rate)/$v(pps)] m1] -fill $v(fg) 474$c create line -1 0 -1 $v(toth) -width 1 -tags [list mark [expr 0 * $v(rate)/$v(pps)] m2] -fill $v(fg) 475 476bind all <Control-l> { 477 set n 0 478 if {$labels == {}} return 479 while {[lindex [$c coords lab$n] 0] < [expr $v(width) * [lindex [$c xview] 0]]} { incr n } 480 481 $c focus lab$n 482 focus $c 483 $c icursor lab$n 0 484 set i 0 485 SetMsg [lindex $labels $i] $i 486 SetUndo $labels 487} 488 489$c bind text <Control-p> { 490 set __x [lindex [%W coords [%W focus]] 0] 491 set __y [lindex [%W coords [%W focus]] 1] 492 set __n [lindex [$c gettags [$c find closest $__x $__y]] 0] 493 PlayNthLab $__n 494 break 495} 496 497$c bind text <Button-1> { 498 %W focus current 499 %W icursor current @[$c canvasx %x],[$c canvasy %y] 500 set i [lindex [$c gettags [%W focus]] 0] 501 SetMsg [lindex $labels $i] $i 502 SetUndo $labels 503} 504 505event add <<Delete>> <Delete> 506catch {event add <<Delete>> <hpDeleteChar>} 507 508$c bind text <<Delete>> { 509 if {[%W focus] != {}} { 510 %W dchars [%W focus] insert 511 SetLabelText [lindex [$c gettags [%W focus]] 0] [$c itemcget [%W focus] -text] 512 set i [lindex [$c gettags [%W focus]] 0] 513 SetMsg [lindex $labels $i] $i 514 } 515} 516 517$c bind text <BackSpace> { 518 if {[%W focus] != {}} { 519 set _tmp [%W focus] 520 set _ind [expr [%W index $_tmp insert]-1] 521 if {$_ind >= 0} { 522 %W icursor $_tmp $_ind 523 %W dchars $_tmp insert 524 SetLabelText [lindex [$c gettags [%W focus]] 0] [$c itemcget [%W focus] -text] 525 set i [lindex [$c gettags [%W focus]] 0] 526 SetMsg [lindex $labels $i] $i 527 } 528 unset _tmp _ind 529 } 530} 531 532$c bind text <Return> { 533 %W insert current insert "" 534 %W focus {} 535} 536 537$c bind text <Enter> { 538 %W insert current insert "" 539 %W focus {} 540} 541 542$c bind text <Control-Any-Key> { break } 543 544$c bind text <Any-Key> { 545 if {[%W focus] != {}} { 546 %W insert [%W focus] insert %A 547 SetLabelText [lindex [$c gettags [%W focus]] 0] [$c itemcget [%W focus] -text] 548 set i [lindex [$c gettags [%W focus]] 0] 549 SetMsg [lindex $labels $i] $i 550 } 551 set v(labchanged) 1 552} 553 554$c bind text <space> { 555 if {[%W focus] != {}} { 556 %W insert [%W focus] insert _ 557 SetLabelText [lindex [$c gettags [%W focus]] 0] [$c itemcget [%W focus] -text] 558 set i [lindex [$c gettags [%W focus]] 0] 559 SetMsg [lindex $labels $i] $i 560 } 561} 562 563$c bind text <Key-Right> { 564 if {[%W focus] != {}} { 565 set __index [%W index [%W focus] insert] 566 %W icursor [%W focus] [expr $__index + 1] 567 if {$__index == [%W index [%W focus] insert]} { 568 set __focus [expr [lindex [$c gettags [%W focus]] 0] + 1] 569 %W focus lab$__focus 570 %W icursor lab$__focus 0 571 set i [lindex [$c gettags [%W focus]] 0] 572 SetMsg [lindex $labels $i] $i 573 while {[expr $v(width) * [lindex [$c xview] 1] -10] < [lindex [%W coords [%W focus]] 0] && [lindex [$c xview] 1] < 1} { 574 $c xview scroll 1 unit 575 } 576 } 577 } 578} 579 580$c bind text <Key-Left> { 581 if {[%W focus] != {}} { 582 set __index [%W index [%W focus] insert] 583 %W icursor [%W focus] [expr [%W index [%W focus] insert] - 1] 584 if {$__index == [%W index [%W focus] insert]} { 585 set __focus [expr [lindex [$c gettags [%W focus]] 0] - 1] 586 %W focus lab$__focus 587 %W icursor lab$__focus end 588 set i [lindex [$c gettags [%W focus]] 0] 589 SetMsg [lindex $labels $i] $i 590 while {[expr $v(width) * [lindex [$c xview] 0] +10] > [lindex [%W coords [%W focus]] 0] && [lindex [$c xview] 0] > 0} { 591 $c xview scroll -1 unit 592 } 593 } 594 } 595} 596 597set _mx 1 598set _mb 0 599#$c bind bound <B1-Motion> { MoveBoundary %x } 600$c bind bound <ButtonRelease-1> { set _mb 0 ; Redraw quick } 601$c bind m1 <B1-Motion> { PutMarker m1 %x %y 1 } 602$c bind m2 <B1-Motion> { PutMarker m2 %x %y 1 } 603$c bind m1 <ButtonPress-1> { set _mx 0 } 604$c bind m2 <ButtonPress-1> { set _mx 0 } 605$c bind obj <ButtonPress-1> { PutMarker m1 %x %y 1 } 606$c bind obj <B1-Motion> { PutMarker m2 %x %y 1 } 607$c bind m1 <ButtonRelease-1> { SendPutMarker m1 %x ; set _mx 0 } 608$c bind m2 <ButtonRelease-1> { SendPutMarker m2 %x ; set _mx 0 } 609$c bind bound <Any-Enter> { BoundaryEnter %x } 610$c bind mark <Any-Enter> { MarkerEnter %x } 611$c bind bound <Any-Leave> { BoundaryLeave %x } 612$c bind mark <Any-Leave> { MarkerLeave %x } 613 614bind $c <ButtonPress-1> { 615 if {%y > [expr $v(waveh)+$v(spegh)+$v(timeh)]} { 616 } else { 617 PutMarker m1 %x %y 1 618 SendPutMarker m1 %x 619 set _mx 1 620 } 621} 622 623bind $c <ButtonRelease-1> { 624 set _mb 0 625 if {%y > [expr $v(waveh)+$v(spegh)+$v(timeh)]} { 626 focus %W 627 if {[%W find overlapping [expr [$c canvasx %x]-2] [expr [$c canvasy %y]-2] [expr [$c canvasx %x]+2] [expr [$c canvasy %y]+2]] == {}} { 628 %W focus {} 629 } 630 } else { 631 PutMarker m2 %x %y 1 632 SendPutMarker m2 %x 633 set _mx 1 634 } 635} 636bind $c <Delete> Cut 637bind $c <Motion> { PutCrossHairs %x %y } 638bind $c <Leave> { 639 $c coords ch1 -1 -1 -1 -1 640 $c coords ch2 -1 -1 -1 -1 641} 642 643if {[string match macintosh $::tcl_platform(platform)] || \ 644 [string match Darwin $::tcl_platform(os)]} { 645 bind $c <Control-1> { PopUpMenu %X %Y %x %y } 646} else { 647 bind $c <3> { PopUpMenu %X %Y %x %y } 648} 649 650bind .cf.fc.xscroll <ButtonRelease-1> SendXScroll 651bind .bf.lab <Any-KeyRelease> { InputFromMsgLine %K } 652bind all <Control-c> Exit 653wm protocol . WM_DELETE_WINDOW Exit 654bind .cf.fc.c <Configure> { if {"%W" == ".cf.fc.c"} Reconf } 655bind $c <F1> { PlayToCursor %x } 656bind $c <2> { PlayToCursor %x } 657focus $c 658 659proc RecentFile fn { 660 global recentFiles 661 662 if {$fn == ""} return 663 if [info exists recentFiles] { 664 foreach e $recentFiles { 665 snack::menuDelete File $e 666 } 667 snack::menuDeleteByIndex File 10 668 } else { 669 set recentFiles {} 670 } 671 snack::menuDelete File Exit 672 set index [lsearch -exact $recentFiles $fn] 673 if {$index != -1} { 674 set recentFiles [lreplace $recentFiles $index $index] 675 } 676 set recentFiles [linsert $recentFiles 0 $fn] 677 if {[llength $recentFiles] > 6} { 678 set recentFiles [lreplace $recentFiles 6 end] 679 } 680 foreach e $recentFiles { 681 snack::menuCommand File $e [list OpenFiles $e] 682 } 683 snack::menuSeparator File 684 snack::menuCommand File Exit Exit 685 if [catch {open [file join ~ .xsrf] w} out] { 686 } else { 687 puts $out "set recentFiles \[list $recentFiles\]" 688 close $out 689 } 690} 691 692set extTypes [list {TIMIT .phn} {MIX .smp.mix} {HTK .lab} {WAVES .lab}] 693set loadTypes [list {{MIX Files} {.mix}} {{HTK Label Files} {.lab}} {{TIMIT Label Files} {.phn}} {{TIMIT Label Files} {.wrd}} {{Waves Label Files} {.lab}}] 694set loadKeys [list MIX HTK TIMIT WAVES] 695set saveTypes {} 696set saveKeys {} 697 698if {[info exists snack::snacksphere]} { 699 lappend extTypes {SPHERE .sph} {SPHERE .wav} 700 lappend loadTypes {{SPHERE Files} {.sph}} {{SPHERE Files} {.wav}} 701 lappend loadKeys SPHERE SPHERE 702} 703if {[info exists snack::snackogg]} { 704 lappend extTypes {OGG .ogg} 705 lappend loadTypes {{Ogg Vorbis Files} {.ogg}} 706 lappend loadKeys OGG 707 lappend saveTypes {{Ogg Vorbis Files} {.ogg}} 708 lappend saveKeys OGG 709 710 proc OggSettings {text} { 711 set w .ogg 712 catch {destroy $w} 713 toplevel $w 714 wm title $w "Ogg Vorbis Settings" 715 716 pack [frame $w.f1] -anchor w 717 pack [label $w.f1.l -text "Nominal bitrate:" -widt 16 -anchor w] -side left 718 pack [entry $w.f1.e -textvar ::ogg(nombr) -wi 7] -side left 719 720 pack [frame $w.f2] -anchor w 721 pack [label $w.f2.l -text "Max bitrate:" -width 16 -anchor w] -side left 722 pack [entry $w.f2.e -textvar ::ogg(maxbr) -wi 7] -side left 723 724 pack [frame $w.f3] -anchor w 725 pack [label $w.f3.l -text "Min bitrate:" -width 16 -anchor w] -side left 726 pack [entry $w.f3.e -textvar ::ogg(minbr) -wi 7] -side left 727 728 pack [frame $w.f4] -anchor w 729 pack [label $w.f4.l -text "Comment:" -width 16 -anchor w] -side left 730 pack [entry $w.f4.e -textvar ::ogg(com) -wi 40] -side left 731 732 pack [frame $w.f5] -anchor w 733 pack [checkbutton $w.f5.b -text "Query settings before saving" \ 734 -variable ::ogg(query) -anchor w] -side left 735 736 pack [frame $w.fb] -side bottom -fill x 737 pack [button $w.fb.cb -text $text -command "destroy $w"] -side top 738 } 739} 740 741snack::addExtTypes $extTypes 742snack::addLoadTypes $loadTypes $loadKeys 743 744proc GetOpenFileName {} { 745 global f v 746 747 if {$v(smpchanged) || $v(labchanged)} { 748 if {[tk_messageBox -message "You have unsaved changes.\n Do you \ 749 really want to close?" -type yesno \ 750 -icon question] == "no"} return 751 } 752 753 set gotfn [snack::getOpenFile -initialdir $f(spath) \ 754 -initialfile $f(sndfile) -format $v(smpfmt)] 755 756 # Ugly hack for Tk8.0 757 if {$gotfn != ""} { 758 set tmp [file split $gotfn] 759 if {[lindex $tmp 0] == [lindex $tmp 1]} { 760 set tmp [lreplace $tmp 0 0] 761 set gotfn [eval file join $tmp] 762 } 763 } 764 update 765 if [string compare $gotfn ""] { 766 OpenFiles $gotfn 767 } 768} 769 770proc GetSaveFileName {title} { 771 global f v labels 772 773 if {$labels != {} && [string compare $title "Save sample file"] != 0} { 774 switch $v(labfmt) { 775 MIX { 776 lappend ::saveTypes {{MIX Files} {.mix}} 777 lappend ::saveKeys MIX 778 } 779 HTK { 780 lappend ::saveTypes {{HTK Label Files} {.lab}} 781 lappend ::saveKeys HTK 782 } 783 TIMIT { 784 lappend ::saveTypes {{TIMIT Label Files} {.phn}} {{TIMIT Label Files} {.wrd}} 785 lappend ::saveKeys TIMIT 786 } 787 WAVES { 788 lappend ::saveTypes {{Waves Label Files} {.lab}} 789 lappend ::saveKeys WAVES 790 } 791 default 792 } 793 snack::addSaveTypes $::saveTypes $::saveKeys 794 795 set gotfn [snack::getSaveFile -initialdir $f(lpath) -initialfile $f(labfile) -format $v(labfmt) -title $title] 796 } else { 797 snack::addSaveTypes $::saveTypes $::saveKeys 798 799 set gotfn [snack::getSaveFile -initialdir $f(spath) -initialfile $f(sndfile) -format $v(smpfmt) -title $title] 800 } 801# set tmp [string trimright $f(lpath) /]. 802# if {[regexp $tmp $gotfn] == 1 && $tmp != "."} { 803# return "" 804# } 805 update 806 return $gotfn 807} 808 809proc SaveAs {} { 810 set gotfn [GetSaveFileName ""] 811 if {[string compare $gotfn ""] != 0} { 812 SaveFile $gotfn 813 } 814} 815 816proc Save {} { 817 global f v 818 819 set fn $f(spath)$f(sndfile) 820 if {[string compare $f(spath)$f(sndfile) ""] == 0} { 821 set fn [GetSaveFileName "Save sample file"] 822 } 823 if {$fn != "" && $v(smpchanged)} { 824 SaveFile $fn 825 } 826 if $v(labchanged) { 827 set fn $f(lpath)$f(labfile) 828 if {[string compare $f(lpath)$f(labfile) ""] == 0} { 829 set fn [GetSaveFileName "Save label file"] 830 } 831 if {$fn != ""} { 832 SaveFile $fn 833 } 834 } 835} 836 837proc SaveFile {{fn ""}} { 838 global f v labels 839 840 SetCursor watch 841 set strip_fn [lindex [file split [file rootname $fn]] end] 842 set ext [file extension $fn] 843 if [string match macintosh $::tcl_platform(platform)] { 844 set path [file dirname $fn]: 845 } else { 846 set path [file dirname $fn]/ 847 } 848 if {$path == "./"} { set path ""} 849 if {![IsLabelFile $fn]} { 850 if {[info exists snack::snackogg]} { 851 if {$::ogg(query) && [string match -nocase .ogg $ext]} { 852 OggSettings Continue 853 tkwait window .ogg 854 } 855 if [catch {snd write $fn -progress snack::progressCallback \ 856 -nominalbitrate $::ogg(nombr) -maxbitrate $::ogg(maxbr) \ 857 -minbitrate $::ogg(minbr) -comment $::ogg(com)} msg] { 858 SetMsg "Save cancelled: $msg" 859 } 860 } else { 861 if [catch {snd write $fn -progress snack::progressCallback} msg] { 862 SetMsg "Save cancelled: $msg" 863 } 864 } 865 if {$v(linkfile)} { 866 snd configure -file $fn 867 } 868 set v(smpchanged) 0 869 wm title . "xs: $fn" 870 set f(spath) $path 871 set f(sndfile) $strip_fn$ext 872 } elseif {$labels != {}} { 873 SaveLabelFile $labels $fn 874 set v(labchanged) 0 875 wm title . "xs: $f(spath)$f(sndfile) - $fn" 876 set f(lpath) $path 877 set f(labfile) $strip_fn$ext 878 } 879 SetCursor "" 880} 881 882proc IsLabelFile {fn} { 883 set ext [file extension $fn] 884 if {$ext == ".lab"} { return 1 } 885 if {$ext == ".mix"} { return 1 } 886 if {$ext == ".phn"} { return 1 } 887 if {$ext == ".wrd"} { return 1 } 888 return 0 889} 890 891proc OpenFiles {fn} { 892 global c labels v f 893 894 895 if {![file readable $fn]} { 896 tk_messageBox -icon warning -type ok -message "No such file: $fn" 897 return 898 } 899 SetCursor watch 900 set strip_fn [lindex [file split [file rootname $fn]] end] 901 set ext [file extension $fn] 902 if [string match macintosh $::tcl_platform(platform)] { 903 set path [file dirname $fn]: 904 } else { 905 set path [file dirname $fn]/ 906 } 907 if {$path == "./"} { set path ""} 908 909 if [IsLabelFile $fn] { 910 set type "lab" 911 set f(lpath) $path 912 } else { 913 set type "smp" 914 set f(spath) $path 915 } 916 917 switch $ext { 918 .mix { 919 set f(labfile) "$strip_fn.mix" 920 set v(labfmt) MIX 921 if $v(autoload) { 922 set f(sndfile) "$strip_fn" 923 if {$f(spath) == ""} { set f(spath) $f(lpath) } 924 if {[file exists $f(spath)$f(sndfile)] == 0} { 925 set f(sndfile) "$strip_fn.smp" 926 } 927 } 928 } 929 .lab { 930 set f(labfile) "$strip_fn.lab" 931 if {$v(smpfmt) == "SD"} { 932 set v(labfmt) WAVES 933 set v(labalign) e 934 if $v(autoload) { 935 set f(sndfile) "$strip_fn.sd" 936 if {$f(spath) == ""} { set f(spath) $f(lpath) } 937 } 938 } else { 939 set v(labfmt) HTK 940 if $v(autoload) { 941 set f(sndfile) "$strip_fn.smp" 942 if {$f(spath) == ""} { set f(spath) $f(lpath) } 943 } 944 } 945 } 946 .phn { 947 set f(labfile) "$strip_fn.phn" 948 set v(labfmt) TIMIT 949 if $v(autoload) { 950 set f(sndfile) "$strip_fn.wav" 951 if {$f(spath) == ""} { set f(spath) $f(lpath) } 952 } 953 } 954 .wrd { 955 set f(labfile) "$strip_fn.wrd" 956 set v(labfmt) TIMIT 957 if $v(autoload) { 958 set f(sndfile) "$strip_fn.wav" 959 if {$f(spath) == ""} { set f(spath) $f(lpath) } 960 } 961 } 962 .smp { 963 set f(sndfile) "$strip_fn.smp" 964 set v(labfmt) MIX 965 if $v(autoload) { 966 set f(labfile) "$strip_fn.smp.mix" 967 if {$f(lpath) == ""} { set f(lpath) $f(spath) } 968 if {[file exists $f(lpath)$f(labfile)] == 0} { 969 set f(labfile) "$strip_fn.mix" 970 } 971 } 972 } 973 .wav { 974 set f(sndfile) "$strip_fn.wav" 975 set v(labfmt) TIMIT 976 if $v(autoload) { 977 set f(labfile) "$strip_fn.phn" 978 if {$f(lpath) == ""} { set f(lpath) $f(spath) } 979 } 980 } 981 .sd { 982 set f(sndfile) "$strip_fn.sd" 983 set v(labfmt) WAVES 984 if $v(autoload) { 985 set f(labfile) "$strip_fn.lab" 986 if {$f(lpath) == ""} { set f(lpath) $f(spath) } 987 } 988 } 989 .bin { 990 set f(sndfile) "$strip_fn.bin" 991 set v(labfmt) HTK 992 if $v(autoload) { 993 set f(labfile) "$strip_fn.lab" 994 if {$f(lpath) == ""} { set f(lpath) $f(spath) } 995 } 996 } 997 default { 998 if {$type == "smp"} { 999 set f(sndfile) "$strip_fn$ext" 1000 if $v(autoload) { 1001 set f(labfile) "$strip_fn$ext.mix" 1002 set v(labfmt) MIX 1003 if {$f(lpath) == ""} { set f(lpath) $f(spath) } 1004 } 1005 } else { 1006 set f(labfile) "$strip_fn$ext" 1007 if $v(autoload) { 1008 set f(sndfile) "$strip_fn.smp" 1009 if {$f(spath) == ""} { set f(spath) $f(lpath) } 1010 } 1011 } 1012 } 1013 } 1014 1015 if {($v(autoload) == 1) || ($type == "smp")} { 1016 $c delete wave speg 1017 .of.c delete overwave 1018 catch {.sect.c delete sect} 1019 StopPlay 1020 1021 set f(byteOrder) [snd cget -byteorder] 1022 set tmps [snack::sound -debug $::debug] 1023 set ffmt [$tmps read $f(spath)$f(sndfile) -end 1 -guessproperties 1] 1024 if {$ffmt == "RAW"} { 1025 set v(rate) [$tmps cget -rate] 1026 set v(sfmt) [$tmps cget -encoding] 1027 set v(chan) [$tmps cget -channels] 1028 set f(byteOrder) [$tmps cget -byteorder] 1029 if {[InterpretRawDialog] == "cancel"} { 1030 $tmps destroy 1031 SetCursor "" 1032 return 1033 } 1034 } 1035 $tmps destroy 1036 if {$v(linkfile)} { 1037 if [catch {snd configure -file $f(spath)$f(sndfile) \ 1038 -skip $f(skip) -byteorder $f(byteOrder) \ 1039 -rate $v(rate) -encoding $v(sfmt) -channels $v(chan) \ 1040 } ret] { 1041 SetMsg "$ret" 1042 return 1043 } 1044 set v(smpfmt) [lindex [snd info] 6] 1045 } else { 1046 if [catch {set v(smpfmt) [snd read $f(spath)$f(sndfile) \ 1047 -skip $f(skip) -byteorder $f(byteOrder) \ 1048 -rate $v(rate) -encoding $v(sfmt) -channels $v(chan) \ 1049 -progress snack::progressCallback]} ret] { 1050 SetMsg "$ret" 1051 return 1052 } 1053 } 1054 set v(rate) [snd cget -rate] 1055 set v(sfmt) [snd cget -encoding] 1056 set v(chan) [snd cget -channels] 1057 set v(startsmp) 0 1058 if {[snd cget -channels] == 1} { 1059 set v(vchan) -1 1060 } 1061 set v(smpchanged) 0 1062 .tb.undo config -state disabled 1063 if {![regexp $v(rate) [snack::audio rates]]} { 1064 tk_messageBox -icon warning -type ok -message "You need to \ 1065 convert this sound\nif you want to play it" 1066 } 1067 } 1068 if {($v(autoload) == 1) || ($type == "lab")} { 1069 set labels [OpenLabelFile $f(lpath)$f(labfile)] 1070 if {$labels == {}} { set f(labfile) "" } 1071 } 1072 if {$labels == {}} { 1073 wm title . "xs: $f(spath)$f(sndfile)" 1074 } else { 1075 wm title . "xs: $f(spath)$f(sndfile) - $f(lpath)$f(labfile)" 1076 } 1077 1078 if {[snd length -unit seconds] > 50 && $v(pps) > 100} { 1079 set v(pps) [expr $v(pps)/10] 1080 } 1081 if {[snd length -unit seconds] < 50 && $v(pps) < 100} { 1082 set v(pps) [expr $v(pps)*10] 1083 } 1084 wm geometry . {} 1085 Redraw 1086 event generate .cf.fc.c <Configure> 1087 SetMsg [InfoStr nopath] 1088# MarkAll 1089 RecentFile $f(spath)$f(sndfile) 1090} 1091 1092proc InterpretRawDialog {} { 1093 global f v 1094 1095 set w .rawDialog 1096 toplevel $w -class Dialog 1097 frame $w.q 1098 pack $w.q -expand 1 -fill both -side top 1099 pack [frame $w.q.f1] -side left -anchor nw -padx 3m -pady 2m 1100 pack [frame $w.q.f2] -side left -anchor nw -padx 3m -pady 2m 1101 pack [frame $w.q.f3] -side left -anchor nw -padx 3m -pady 2m 1102 pack [frame $w.q.f4] -side left -anchor nw -padx 3m -pady 2m 1103 pack [label $w.q.f1.l -text "Sample Rate"] 1104 foreach e [snack::audio rates] { 1105 pack [radiobutton $w.q.f1.r$e -text $e -val $e -var ::v(rate)]\ 1106 -anchor w 1107 } 1108 pack [label $w.q.f2.l -text "Sample Encoding"] 1109 foreach e [snack::audio encodings] { 1110 pack [radiobutton $w.q.f2.r$e -text $e -val $e -var ::v(sfmt)]\ 1111 -anchor w 1112 } 1113 pack [label $w.q.f3.l -text Channels] 1114 pack [radiobutton $w.q.f3.r1 -text Mono -val 1 -var ::v(chan)] -anchor w 1115 pack [radiobutton $w.q.f3.r2 -text Stereo -val 2 -var ::v(chan)] -anchor w 1116 pack [radiobutton $w.q.f3.r4 -text 4 -val 4 -var ::v(chan)] -anchor w 1117 pack [entry $w.q.f3.e -textvariable ::v(chan) -width 3] -anchor w 1118 pack [label $w.q.f4.l -text "Byte Order"] 1119 pack [radiobutton $w.q.f4.ri -text "Little Endian\n(Intel)" \ 1120 -value littleEndian -var ::f(byteOrder)] -anchor w 1121 pack [radiobutton $w.q.f4.rm -text "Big Endian\n(Motorola)" \ 1122 -value bigEndian -var ::f(byteOrder)] -anchor w 1123 pack [label $w.q.f4.l2 -text "\nRead Offset (bytes)"] 1124 pack [entry $w.q.f4.e -textvar f(skip) -wi 6] 1125 snack::makeDialogBox $w -title "Interpret Raw File As" -type okcancel \ 1126 -default ok 1127} 1128 1129proc Link2File {} { 1130 global f v 1131 1132 StopPlay 1133 if {$v(smpchanged)} { 1134 if {[tk_messageBox -message "You have unsaved changes.\n Do you \ 1135 really want to loose them?" -type yesno \ 1136 -icon question] == "no"} return 1137 } 1138 set v(smpchanged) 0 1139 if {$v(linkfile)} { 1140 .of.c delete overwave 1141 catch {.sect.c delete sect} 1142 if {$f(sndfile) == ""} { 1143 snd configure -file _xs[pid].wav 1144 } else { 1145 snd configure -file $f(spath)$f(sndfile) 1146 } 1147 cbs configure -file "" 1148 } else { 1149 if {$f(sndfile) == ""} { 1150 snd config -load "" 1151 } else { 1152 snd config -load $f(spath)$f(sndfile) 1153 } 1154 cbs config -load "" 1155 } 1156} 1157 1158proc ConfigEditMenu {} { 1159 global v 1160 1161 if {$v(linkfile)} { 1162 snack::menuEntryOff Edit Cut 1163 snack::menuEntryOff Edit Copy 1164 snack::menuEntryOff Edit Paste 1165 snack::menuEntryOff Edit Crop 1166 } else { 1167 snack::menuEntryOn Edit Cut 1168 snack::menuEntryOn Edit Copy 1169 snack::menuEntryOn Edit Paste 1170 snack::menuEntryOn Edit Crop 1171 } 1172 if {$v(smpchanged)} { 1173 snack::menuEntryOn Edit Undo 1174 } else { 1175 snack::menuEntryOff Edit Undo 1176 } 1177} 1178 1179proc ConfigTransformMenu {} { 1180 global v 1181 1182 if {$v(linkfile)} { 1183 snack::menuEntryOff Transform Conversions 1184 snack::menuEntryOff Transform Amplify... 1185 snack::menuEntryOff Transform Normalize... 1186 snack::menuEntryOff Transform Echo... 1187 snack::menuEntryOff Transform {Mix Channels...} 1188 snack::menuEntryOff Transform Invert 1189 snack::menuEntryOff Transform Reverse 1190 snack::menuEntryOff Transform Silence 1191 snack::menuEntryOff Transform {Remove DC} 1192 } else { 1193 snack::menuEntryOn Transform Conversions 1194 snack::menuEntryOn Transform Amplify... 1195 snack::menuEntryOn Transform Normalize... 1196 snack::menuEntryOn Transform Echo... 1197 snack::menuEntryOn Transform {Mix Channels...} 1198 snack::menuEntryOn Transform Invert 1199 snack::menuEntryOn Transform Reverse 1200 snack::menuEntryOn Transform Silence 1201 snack::menuEntryOn Transform {Remove DC} 1202 } 1203 if {[snd cget -channels] == 1} { 1204 snack::menuEntryOff Transform {Mix Channels...} 1205 } 1206} 1207 1208proc ConfigOptionsMenu {} { 1209 global v 1210 1211 if {[snd cget -channels] == 1} { 1212 snack::menuEntryOff Options {View Channel} 1213 } else { 1214 snack::menuEntryOn Options {View Channel} 1215 } 1216} 1217 1218proc OpenLabelFile {fn} { 1219 global f v undo 1220 1221 if [catch {open $fn} in] { 1222 SetMsg $in 1223 return {} 1224 } else { 1225 if [catch {set labelfile [read $in]}] { return {} } 1226 set l {} 1227 set undo {} 1228 set v(labchanged) 0 1229 .tb.undo config -state disabled 1230 close $in 1231 switch $v(labfmt) { 1232 TIMIT - 1233 HTK { 1234 foreach row [split $labelfile \n] { 1235 set rest "" 1236 if {[scan $row {%d %d %s %[^�]} start stop label rest] >= 3} { 1237 lappend l "$start\n$stop\n$label\n$rest" 1238 } 1239 } 1240 } 1241 MIX { 1242 set f(header) "" 1243 set getHead 1 1244 foreach row [split $labelfile \n] { 1245 if [string match FR* $row] { 1246 set getHead 0 1247 set rest "" 1248 if {[scan $row {%s %d %s %[^�]} junk start label rest] >= 3} { 1249 lappend l "$start\n$label\n$rest" 1250 } 1251 } else { 1252 if {$getHead == 1} { 1253 set f(header) [lappend f(header) $row] 1254 } 1255 } 1256 } 1257 } 1258 WAVES { 1259 set f(header) "" 1260 set getHead 1 1261 foreach row [split $labelfile \n] { 1262 if {$getHead == 1} { 1263 set f(header) [lappend f(header) $row] 1264 if [string match # $row] { set getHead 0 } 1265 continue 1266 } 1267 set rest "" 1268 if {[scan $row {%f %d %s %[^�]} end color label rest] >= 3} { 1269 lappend l "$end\n$color\n$label\n$rest" 1270 } 1271 } 1272 } 1273 } 1274 } 1275 return $l 1276} 1277 1278proc SaveLabelFile {labels fn} { 1279 global f v 1280 1281 if {$fn == "" || [regexp /$ $fn] == 1 || $labels == {}} return 1282 set f(labfile) [file tail $fn] 1283 if [string match macintosh $::tcl_platform(platform)] { 1284 set f(lpath) [file dirname $fn]: 1285 } else { 1286 set f(lpath) [file dirname $fn]/ 1287 } 1288 catch {file copy $fn $fn~} 1289 if [catch {open $fn w} out] { 1290 SetMsg $out 1291 return 1292 } else { 1293 set v(labchanged) 0 1294 fconfigure $out -translation {auto lf} 1295 switch $v(labfmt) { 1296 TIMIT - 1297 HTK { 1298 foreach row $labels { 1299 puts $out [join $row " "] 1300 } 1301 } 1302 MIX { 1303 if {$f(header) != ""} { 1304 puts $out [join $f(header) \n] 1305 } else { 1306 puts $out "NOLABELS\nTEXT: \nCT 1" 1307 } 1308 foreach row $labels { 1309 set t4 [split $row \n] 1310 set lab [lindex $t4 1] 1311 if {[string compare $lab "OK"] == 0} { 1312 } elseif {[string index $lab 0] == "$"} { 1313 } elseif {[string index $lab 0] == "#"} { 1314 } else { 1315 set t4 [lreplace $t4 1 1 "\$$lab"] 1316 } 1317 set t5 [join $t4 "\t"] 1318 puts $out "FR\t$t5" 1319 } 1320 } 1321 WAVES { 1322 if {$f(header) != ""} { 1323 puts $out [join $f(header) \n] 1324 } else { 1325 set name [lindex [file split [file rootname $fn]] end] 1326 set date [clock format [clock seconds] -format "%a %b %d %H:%M:%S %Y"] 1327 puts $out "signal $name" 1328 puts $out "type 0\ncolor 121" 1329 puts $out "comment created using xs $date" 1330 puts $out "font -misc-*-bold-*-*-*-15-*-*-*-*-*-*-*" 1331 puts $out "separator ;\nnfields 1\n#" 1332 } 1333 foreach row $labels { 1334 set rest "" 1335 scan $row {%f %d %s %[^�]} end color label rest 1336 puts $out [format " %.6f %d %s %s" $end $color $label $rest] 1337 } 1338 } 1339 } 1340 close $out 1341 } 1342 SetMsg "Saved: $fn" 1343} 1344 1345proc SaveMark {} { 1346 global f v labels 1347 1348 set start [Marker2Sample m1] 1349 set end [Marker2Sample m2] 1350 1351 set gotfn [snack::getSaveFile -initialdir $f(spath) -format $v(smpfmt)] 1352 1353 if [string compare $gotfn ""] { 1354 SetMsg "Saving range: $start $end" 1355 1356 set ext [file extension $gotfn] 1357 set root [file rootname $gotfn] 1358 if {$root == $gotfn} { 1359 set fn $root[file extension $f(sndfile)] 1360 } else { 1361 set fn $gotfn 1362 } 1363 if [catch {snd write $fn -start $start -end $end \ 1364 -progress snack::progressCallback}] { 1365 SetMsg "Save cancelled" 1366 } 1367 if {$labels != {}} { 1368 set fn $root[file extension $f(labfile)] 1369 switch $v(labfmt) { 1370 WAVES - 1371 HTK { 1372 SaveLabelFile [CropLabels [Marker2Time m1] [Marker2Time m2]] $fn 1373 } 1374 TIMIT - 1375 MIX { 1376 SaveLabelFile [CropLabels $start $end] $fn 1377 } 1378 } 1379 } 1380 } 1381} 1382 1383proc Close {} { 1384 global labels f v c 1385 1386 if {$v(smpchanged) || $v(labchanged)} { 1387 if {[tk_messageBox -message "You have unsaved changes.\n Do you \ 1388 really want to close?" -type yesno \ 1389 -icon question] == "no"} return 1390 } 1391 StopPlay 1392 set labels {} 1393 set v(smpchanged) 0 1394 set v(labchanged) 0 1395 set undo {} 1396 .tb.undo config -state disabled 1397 set f(labfile) "" 1398 set f(sndfile) "" 1399 wm title . "xs:" 1400 if {$v(linkfile)} { 1401 catch {file delete -force _xs[pid].wav} 1402 snd configure -file _xs[pid].wav 1403 } else { 1404 snd flush 1405 } 1406 Redraw 1407} 1408 1409proc Exit {} { 1410 global v 1411 1412 if {$v(smpchanged) || $v(labchanged)} { 1413 if {[tk_messageBox -message \ 1414 "You have unsaved changes.\n Do you really want to quit?" \ 1415 -type yesno -icon question] == "no"} { 1416 return 1417 } 1418 } 1419 catch {file delete -force _xs[pid].wav} 1420 exit 1421} 1422 1423proc OpenGetURLWindow {} { 1424 global f v 1425 1426 if {$v(linkfile)} { 1427 tk_messageBox -icon warning -type ok -message "This function not \ 1428 available\nwhen using link to disk file." 1429 return 1430 } 1431 1432 set w .geturl 1433 catch {destroy $w} 1434 toplevel $w 1435 wm title $w {Get URL} 1436 wm geometry $w [xsGetGeometry] 1437 1438 set f(url) $f(http) 1439 pack [frame $w.f] 1440 pack [label $w.f.l -text {Enter the World Wide Web location (URL):}] 1441 pack [entry $w.f.e -width 60 -textvar f(url)] 1442 pack [frame $w.f2] 1443 pack [button $w.f2.b1 -text Get -command GetURL] -side left 1444 bind $w.f.e <Key-Return> GetURL 1445 pack [button $w.f2.b2 -text Stop -command StopURL] -side left 1446 pack [button $w.f2.b3 -text Close -command [list destroy $w]] -side left 1447} 1448 1449proc GetURL {} { 1450 global c f 1451 1452 SetCursor watch 1453 $c delete wave speg tran 1454 StopPlay 1455 StopURL 1456 set f(urlToken) [::http::geturl $f(url) -command URLcallback -progress Progress] 1457 set c .cf.fc.c 1458 SetMsg "Fetching: $f(url)" 1459} 1460 1461proc Progress {token total current} { 1462 if {$total > 0} { 1463 set p [expr {int(100 * $current/$total)}] 1464 SetMsg "Fetched $current bytes ($p%)" 1465 } else { 1466 SetMsg "Fetched $current bytes" 1467 } 1468} 1469 1470proc URLcallback {token} { 1471 global f v labels 1472 upvar #0 $token state 1473 1474 SetCursor "" 1475 if {$state(status) != "ok"} { 1476 return 1477 } 1478 if {[string match *200* [::http::code $token]] == 1} { 1479 snd data [::http::data $token] 1480 set f(sndfile) "" 1481 set f(labfile) "" 1482 set v(rate) [snd cget -rate] 1483 set v(sfmt) [snd cget -encoding] 1484 set v(startsmp) 0 1485 set labels {} 1486 wm title . "xs: $f(url)" 1487 Redraw 1488 event generate .cf.fc.c <Configure> 1489 MarkAll 1490 SetMsg [InfoStr nopath] 1491 } else { 1492 SetMsg [::http::code $token] 1493 } 1494 set f(urlToken) "" 1495} 1496 1497proc StopURL {} { 1498 global f v 1499 1500 if {$f(urlToken) != ""} { 1501 ::http::reset $f(urlToken) 1502 } 1503 set f(urlToken) "" 1504 SetMsg "Transfer interrupted." 1505 SetCursor "" 1506} 1507 1508proc Crop {} { 1509 global labels v 1510 1511 set start [Marker2Sample m1] 1512 set end [Marker2Sample m2] 1513 if {$start == $end} return 1514 SetMsg "Cropping to range: $start $end" 1515 1516 cbs copy snd -end [expr {$start - 1}] 1517 cbs insert snd [cbs length] -start [expr {$end + 1}] 1518 snd crop $start $end 1519 1520 set v(undoc) "snd insert cbs 0 -end [expr {$start-1}];snd insert cbs [expr {$end+1}] -start $start" 1521 set v(redoc) "snd crop $start $end" 1522 set v(smpchanged) 1 1523 1524 if {[llength $labels] != 0} { 1525 switch $v(labfmt) { 1526 WAVES - 1527 HTK { 1528 set labels [CropLabels [Marker2Time m1] [Marker2Time m2]] 1529 } 1530 TIMIT - 1531 MIX { 1532 set labels [CropLabels $start $end] 1533 } 1534 } 1535 set v(labchanged) 1 1536 } 1537 PutMarker m1 [DTime2Time 0.0] 0 0 1538 PutMarker m2 [DTime2Time [snd length -unit seconds]] 0 0 1539 .tb.undo config -state normal 1540 DrawOverAxis 1541 Redraw 1542} 1543 1544proc Reverse {} { 1545 global v 1546 1547 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1548 set start [Marker2Sample m1] 1549 set end [Marker2Sample m2] 1550 SetMsg "Reversing range: $start $end" 1551 1552 cbs copy snd 1553 if [catch {snd reverse -start $start -end $end \ 1554 -progress snack::progressCallback}] { 1555 SetMsg "Reverse cancelled" 1556 snd copy cbs 1557 return 1558 } 1559 1560 set v(undoc) "snd reverse -start $start -end $end" 1561 set v(redoc) "snd reverse -start $start -end $end" 1562 set v(smpchanged) 1 1563 .tb.undo config -state normal 1564 Redraw 1565} 1566 1567proc Invert {} { 1568 global v filt 1569 1570 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1571 set start [Marker2Sample m1] 1572 set end [Marker2Sample m2] 1573 SetMsg "Inverting range: $start $end" 1574 1575 $filt(f) configure -1.0 1576 1577 cbs copy snd 1578 if [catch {snd filter $filt(f) -start $start -end $end \ 1579 -progress snack::progressCallback}] { 1580 SetMsg "Invert cancelled" 1581 snd copy cbs 1582 return 1583 } 1584 1585 set v(undoc) "snd swap cbs" 1586 set v(redoc) "snd swap cbs" 1587 set v(smpchanged) 1 1588 .tb.undo config -state normal 1589 Redraw 1590} 1591 1592proc Silence {} { 1593 global v filt 1594 1595 set start [Marker2Sample m1] 1596 set end [Marker2Sample m2] 1597 if {$start == $end} return 1598 SetMsg "Silencing range: $start $end" 1599 1600 $filt(f) configure 0.0 1601 1602 cbs copy snd 1603 if [catch {snd filter $filt(f) -start $start -end $end \ 1604 -progress snack::progressCallback}] { 1605 SetMsg "Silence cancelled" 1606 snd copy cbs 1607 return 1608 } 1609 1610 set v(undoc) "snd swap cbs" 1611 set v(redoc) "snd swap cbs" 1612 set v(smpchanged) 1 1613 .tb.undo config -state normal 1614 Redraw 1615} 1616 1617proc RemoveDC {} { 1618 global v remdc 1619 1620 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1621 set start [Marker2Sample m1] 1622 set end [Marker2Sample m2] 1623 if {$start == $end} return 1624 SetMsg "Removing DC for range: $start $end" 1625 1626 cbs copy snd 1627 if [catch {snd filter $remdc(f) -start $start -end $end \ 1628 -progress snack::progressCallback -continuedrain 0}] { 1629 SetMsg "Remove DC cancelled" 1630 snd copy cbs 1631 return 1632 } 1633 1634 set v(undoc) "snd swap cbs" 1635 set v(redoc) "snd swap cbs" 1636 set v(smpchanged) 1 1637 .tb.undo config -state normal 1638 Redraw 1639} 1640 1641proc ConfAmplify {flag} { 1642 global amplify 1643 1644 set w .amp 1645 if {$amplify(db) == 1} { 1646 $w.f.l configure -text dB 1647 set tmp [expr {20.0*log10(($amplify(v)+0.000000000000000001)/100.0)}] 1648 $w.f.s1 configure -from -96.0 -to 24.0 1649 } else { 1650 $w.f.l configure -text % 1651 set tmp [expr {100.0*pow(10,$amplify(v)/20.0)}] 1652 $w.f.s1 configure -from 0.0 -to 300.0 1653 } 1654 if {$flag} { 1655 set amplify(v) $tmp 1656 } 1657} 1658 1659proc DoAmplify {} { 1660 global v amplify 1661 1662 set start [Marker2Sample m1] 1663 set end [Marker2Sample m2] 1664 if {$start == $end} return 1665 SetMsg "Amplifying range: $start $end" 1666 1667 if {$amplify(db) == 1} { 1668 set tmp [expr {pow(10,$amplify(v)/20.0)}] 1669 } else { 1670 set tmp [expr {$amplify(v) / 100.0}] 1671 } 1672 $amplify(f) configure $tmp 1673 1674 cbs copy snd 1675 if [catch {snd filter $amplify(f) -start $start -end $end \ 1676 -progress snack::progressCallback}] { 1677 SetMsg "Amplify cancelled" 1678 snd copy cbs 1679 return 1680 } 1681 1682 set v(undoc) "snd swap cbs" 1683 set v(redoc) "snd swap cbs" 1684 set v(smpchanged) 1 1685 .tb.undo config -state normal 1686 Redraw 1687} 1688 1689proc Amplify {} { 1690 global amplify 1691 1692 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1693 set w .amp 1694 catch {destroy $w} 1695 toplevel $w 1696 wm title $w {Amplify} 1697 1698 pack [ label $w.l -text "Amplify by:"] 1699 pack [ frame $w.f] -fill both -expand true 1700 pack [ scale $w.f.s1 -command "" -orient horizontal \ 1701 -resolution .1 -showvalue 0 \ 1702 -variable amplify(v)] -side left 1703 pack [entry $w.f.e -textvariable amplify(v) -width 5] -side left 1704 pack [label $w.f.l -text xx -width 2] -side left 1705 pack [checkbutton $w.cb -text "Decibels" -variable amplify(db) \ 1706 -command [list ConfAmplify 1]] 1707 pack [ frame $w.f3] 1708 pack [ button $w.f3.b1 -text OK -width 6 \ 1709 -command "DoAmplify;destroy $w"] -side left 1710 pack [ button $w.f3.b2 -text Cancel -command "destroy $w"] -side left 1711 ConfAmplify 0 1712} 1713 1714proc ConfNormalize {flag} { 1715 global normalize 1716 1717 set w .norm 1718 if {$normalize(db) == 1} { 1719 $w.f.l configure -text dB 1720 set tmp [expr {20.0*log10(($normalize(v)+0.000000000000000001)/100.0)}] 1721 $w.f.s1 configure -from -96.0 -to 0.0 1722 } else { 1723 $w.f.l configure -text % 1724 set tmp [expr {100.0*pow(10,$normalize(v)/20.0)}] 1725 $w.f.s1 configure -from 0.0 -to 100.0 1726 } 1727 if {$flag} { 1728 set normalize(v) $tmp 1729 } 1730 if {[snd cget -channels] == 1} { 1731 $w.cb2 configure -state disabled 1732 } else { 1733 $w.cb2 configure -state normal 1734 } 1735} 1736 1737proc DoNormalize {} { 1738 global v normalize 1739 1740 set start [Marker2Sample m1] 1741 set end [Marker2Sample m2] 1742 if {$start == $end} return 1743 SetMsg "Normalizing range: $start $end" 1744 1745 if {$normalize(db) == 1} { 1746 set tmp [expr {pow(10,$normalize(v)/20.0)}] 1747 } else { 1748 set tmp [expr {$normalize(v) / 100.0}] 1749 } 1750 if {[string match [snd cget -encoding] Lin8]} { 1751 set smax 255.0 1752 } elseif {[string match [snd cget -encoding] Lin24]} { 1753 set smax 8388608.0 1754 } else { 1755 set smax 32767.0 1756 } 1757 for {set c 0} {$c < [snd cget -channels]} {incr c} { 1758 if {$normalize(allEqual)} { 1759 set max [snd max -start $start -end $end] 1760 set min [snd min -start $start -end $end] 1761 } else { 1762 set max [snd max -start $start -end $end -channel $c] 1763 set min [snd min -start $start -end $end -channel $c] 1764 } 1765 if {$max < -$min} { 1766 set max [expr {-$min}] 1767 if {$max > $smax} { 1768 set max $smax 1769 } 1770 } 1771 if {$max == 0} { 1772 set max 1.0 1773 } 1774 set factor [expr {$tmp * $smax / $max}] 1775 lappend factors $factor 1776 if {$normalize(allEqual)} break 1777 if {$c < [expr {[snd cget -channels] - 1}]} { 1778 for {set i 0} {$i < [snd cget -channels]} {incr i} { 1779 lappend factors 0.0 1780 } 1781 } 1782 } 1783 eval $normalize(f) configure $factors 1784 1785 cbs copy snd 1786 if [catch {snd filter $normalize(f) -start $start -end $end \ 1787 -progress snack::progressCallback}] { 1788 SetMsg "Normalize cancelled" 1789 snd copy cbs 1790 return 1791 } 1792 1793 set v(undoc) "snd swap cbs" 1794 set v(redoc) "snd swap cbs" 1795 set v(smpchanged) 1 1796 .tb.undo config -state normal 1797 Redraw 1798} 1799 1800proc Normalize {} { 1801 global normalize 1802 1803 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1804 set w .norm 1805 catch {destroy $w} 1806 toplevel $w 1807 wm title $w {Normalize} 1808 1809 pack [ label $w.l -text "Normalize to:"] 1810 pack [ frame $w.f] -fill both -expand true 1811 pack [ scale $w.f.s1 -command "" -orient horizontal \ 1812 -resolution .1 -showvalue 0 \ 1813 -variable normalize(v)] -side left 1814 pack [entry $w.f.e -textvariable normalize(v) -width 5] -side left 1815 pack [label $w.f.l -text xx -width 2] -side left 1816 pack [checkbutton $w.cb1 -text "Decibels" -variable normalize(db) \ 1817 -command [list ConfNormalize 1] -anchor w] -fill both -expand true 1818 pack [checkbutton $w.cb2 -text "Normalize all channels equally" \ 1819 -variable normalize(allEqual) -anchor w] -fill both -expand true 1820 pack [ frame $w.f3] 1821 pack [ button $w.f3.b1 -text OK -width 6 \ 1822 -command "DoNormalize;destroy $w"] -side left 1823 pack [ button $w.f3.b2 -text Cancel -command "destroy $w"] -side left 1824 ConfNormalize 0 1825} 1826 1827proc ConfEcho {args} { 1828 global echo 1829 1830 set iGain [expr {0.01 * $echo(iGain)}] 1831 set oGain [expr {0.01 * $echo(oGain)}] 1832 set values "$iGain $oGain " 1833 for {set i 1} {$i <= $echo(n)} {incr i} { 1834 set decay [expr {0.01 * $echo(decay$i)}] 1835 append values "$echo(delay$i) $decay " 1836 } 1837 1838 eval $echo(f) configure $values 1839} 1840 1841proc DoEcho {} { 1842 global v echo 1843 1844 set start [Marker2Sample m1] 1845 set end [Marker2Sample m2] 1846 if {$start == $end} return 1847 SetMsg "Applying echo filter to range: $start $end" 1848 1849 ConfEcho 1850 1851 cbs copy snd 1852 if [catch {snd filter $echo(f) -start $start -end $end \ 1853 -continuedrain $echo(drain) \ 1854 -progress snack::progressCallback}] { 1855 SetMsg "Echo filter cancelled" 1856 snd copy cbs 1857 return 1858 } 1859 1860 set v(undoc) "snd swap cbs" 1861 set v(redoc) "snd swap cbs" 1862 set v(smpchanged) 1 1863 .tb.undo config -state normal 1864 Redraw 1865} 1866 1867proc PlayEcho {} { 1868 global echo 1869 1870 set start [Marker2Sample m1] 1871 set end [Marker2Sample m2] 1872 if {$start == $end} return 1873 1874 ConfEcho 1875 1876 snd stop 1877 snd play -filter $echo(f) -start $start -end $end 1878} 1879 1880proc AddEcho {} { 1881 global echo 1882 1883 if {$echo(n) > 9} return 1884 set w .proc 1885 incr echo(n) 1886 AddEchoW $echo(n) 1887} 1888 1889proc AddEchoW {n} { 1890 global echo 1891 1892 set w .proc 1893 set f [expr {$n + 2}] 1894 pack [frame $w.f.f$f -relief raised -bd 1] -side left -before $w.f.hidden 1895 if {![info exists echo(delay$n)]} { 1896 set echo(delay$n) 30.0 1897 } 1898 pack [label $w.f.f$f.l -text "Echo $n"] -side top 1899 pack [frame $w.f.f$f.f1] -side left 1900 pack [scale $w.f.f$f.f1.s -label "" -from 250.0 -to 10.0 \ 1901 -variable echo(delay$n) -command "" -showvalue 0 -command ConfEcho] 1902 pack [frame $w.f.f$f.f1.f] 1903 pack [entry $w.f.f$f.f1.f.e -textvariable echo(delay$n) -width 3] \ 1904 -side left 1905 pack [label $w.f.f$f.f1.f.l -text ms] -side left 1906 1907 if {![info exists echo(decay$n)]} { 1908 set echo(decay$n) 40 1909 } 1910 pack [frame $w.f.f$f.f2] -side left 1911 pack [scale $w.f.f$f.f2.s -label "" -from 100 -to 0 -resolution 1 \ 1912 -variable echo(decay$n) -command "" -showvalue 0 -command ConfEcho] 1913 pack [frame $w.f.f$f.f2.f] 1914 pack [entry $w.f.f$f.f2.f.e -textvariable echo(decay$n) -width 3] \ 1915 -side left 1916 pack [label $w.f.f$f.f2.f.l -text %] -side left 1917} 1918 1919proc RemEcho {} { 1920 global echo 1921 1922 if {$echo(n) < 2} return 1923 1924 set w .proc 1925 set f [expr {$echo(n) + 2}] 1926 destroy $w.f.f$f 1927 incr echo(n) -1 1928} 1929 1930proc Echo {} { 1931 global echo 1932 1933 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 1934 set w .proc 1935 catch {destroy $w} 1936 toplevel $w 1937 wm title $w {Echo} 1938 1939 pack [frame $w.f] 1940 1941 pack [frame $w.f.f1] -side left 1942 pack [label $w.f.f1.l -text In] 1943 pack [scale $w.f.f1.s -label "" -from 100 -to 0 -resolution 1 \ 1944 -variable echo(iGain) -command "" -showvalue 0 -command ConfEcho] 1945 pack [frame $w.f.f1.f] 1946 pack [entry $w.f.f1.f.e -textvariable echo(iGain) -width 3] -side left 1947 pack [label $w.f.f1.f.l -text %] -side left 1948 1949 pack [frame $w.f.f2] -side left 1950 pack [label $w.f.f2.l -text Out] 1951 pack [scale $w.f.f2.s -label "" -from 100 -to 0 -resolution 1 \ 1952 -variable echo(oGain) -command "" -showvalue 0 -command ConfEcho] 1953 pack [frame $w.f.f2.f] 1954 pack [entry $w.f.f2.f.e -textvariable echo(oGain) -width 3] -side left 1955 pack [label $w.f.f2.f.l -text %] -side left 1956 1957 pack [frame $w.f.fe] -side left 1958 pack [button $w.f.fe.1 -text + -command AddEcho] 1959 pack [button $w.f.fe.2 -text - -command RemEcho] 1960 1961 pack [frame $w.f.hidden] -side left 1962 for {set i 1} {$i <= $echo(n)} {incr i} { 1963 AddEchoW $i 1964 } 1965 1966 pack [checkbutton $w.cb -text "Drain beyond selection" \ 1967 -variable echo(drain)] -anchor w 1968 1969 pack [ frame $w.f3] -pady 10 -anchor w 1970 pack [ button $w.f3.b1 -bitmap snackPlay -command PlayEcho] -side left 1971 pack [ button $w.f3.b2 -bitmap snackStop -command "Stop snd"] -side left 1972 pack [ button $w.f3.b3 -text OK -width 6 -command "DoEcho;destroy $w"] \ 1973 -side left 1974 pack [ button $w.f3.b4 -text Cancel -command "destroy $w"] -side left 1975} 1976 1977proc ConfMix {args} { 1978 global mix 1979 1980 set n [snd cget -channels] 1981 for {set i 0} {$i < $n} {incr i} { 1982 for {set j 0} {$j < $n} {incr j} { 1983 set val [expr {0.01 * $mix($i,$j)}] 1984 append values "$val " 1985 } 1986 } 1987 eval $mix(f) configure $values 1988} 1989 1990proc DoMix {} { 1991 global v mix 1992 1993 set start [Marker2Sample m1] 1994 set end [Marker2Sample m2] 1995 if {$start == $end} return 1996 SetMsg "Mixing channels in range: $start $end" 1997 1998 ConfMix 1999 2000 cbs copy snd 2001 if [catch {snd filter $mix(f) -start $start -end $end \ 2002 -progress snack::progressCallback}] { 2003 SetMsg "Mix channels cancelled" 2004 snd copy cbs 2005 return 2006 } 2007 2008 set v(undoc) "snd swap cbs" 2009 set v(redoc) "snd swap cbs" 2010 set v(smpchanged) 1 2011 .tb.undo config -state normal 2012 Redraw 2013} 2014 2015proc PlayMix {} { 2016 global mix 2017 2018 set start [Marker2Sample m1] 2019 set end [Marker2Sample m2] 2020 if {$start == $end} return 2021 2022 ConfMix 2023 2024 snd stop 2025 snd play -filter $mix(f) -start $start -end $end 2026} 2027 2028proc MixChan {} { 2029 global mix 2030 2031 if {[Marker2Sample m1] == [Marker2Sample m2]} MarkAll 2032 set w .mix 2033 catch {destroy $w} 2034 toplevel $w 2035 wm title $w {Mix Channels} 2036 2037 pack [frame $w.f] 2038 2039 label $w.f.l -text "New channel" 2040 grid $w.f.l 2041 2042 set n [snd cget -channels] 2043 2044 for {set i 0} {$i < $n} {incr i} { 2045 if {$i == 0} { 2046 set label Left 2047 } elseif {$i == 1} { 2048 set label Right 2049 } else { 2050 set label [expr {$i + 1}] 2051 } 2052 label $w.f.ly$i -text $label 2053 grid $w.f.ly$i -row [expr {$i + 1}] -column 0 2054 label $w.f.lx$i -text "Channel $label" 2055 grid $w.f.lx$i -row 0 -column [expr {$i + 1}] 2056 for {set j 0} {$j < $n} {incr j} { 2057 if {![info exists mix($i,$j)]} { 2058 if {$i == $j} { 2059 set mix($i,$j) 100 2060 } else { 2061 set mix($i,$j) 0 2062 } 2063 } 2064 frame $w.f.f$i-f$j -relief raised -bd 1 2065 grid $w.f.f$i-f$j -row [expr {$i + 1}] -column [expr {$j + 1}] 2066 pack [scale $w.f.f$i-f$j.s -command "" -orient horizontal \ 2067 -from -100 -to 100 -showvalue 0 -command ConfMix \ 2068 -variable mix($i,$j)] 2069 pack [frame $w.f.f$i-f$j.f] 2070 pack [entry $w.f.f$i-f$j.f.e -textvariable mix($i,$j) -width 4] \ 2071 -side left 2072 pack [label $w.f.f$i-f$j.f.l -text %] -side left 2073 } 2074 } 2075 2076 pack [ frame $w.f3] -pady 10 2077 pack [ button $w.f3.b1 -bitmap snackPlay -command PlayMix] -side left 2078 pack [ button $w.f3.b2 -bitmap snackStop -command "Stop snd"] -side left 2079 pack [ button $w.f3.b3 -text OK -width 6 -command "DoMix;destroy $w"] \ 2080 -side left 2081 pack [ button $w.f3.b4 -text Cancel -command "destroy $w"] -side left 2082} 2083 2084proc Cut {} { 2085 global c v 2086 2087 set start [Marker2Sample m1] 2088 set end [Marker2Sample m2] 2089 if {$start == $end} return 2090 SetMsg "Cutting range: $start $end" 2091 cbs copy snd -start $start -end $end 2092 snd cut $start $end 2093 set v(undoc) "snd insert cbs $start" 2094 set v(redoc) "snd cut $start $end" 2095 2096 PutMarker m2 [Marker2Time m1] 0 0 2097 set v(smpchanged) 1 2098 .tb.undo config -state normal 2099 DrawOverAxis 2100 Redraw 2101} 2102 2103proc Copy {} { 2104 set start [Marker2Sample m1] 2105 set end [Marker2Sample m2] 2106 if {$start == $end} return 2107 SetMsg "Copying range: $start $end" 2108 cbs copy snd -start $start -end $end 2109} 2110 2111proc Paste {} { 2112 global c v 2113 2114 set start [Marker2Sample m1] 2115 set startt [Marker2Time m1] 2116 if {$start > [snd length]} { 2117 set start [snd length] 2118 set startt [snd length -unit seconds] 2119 } 2120 SetMsg "Inserting at: $start" 2121 snd insert cbs $start 2122 2123 set tmp [expr {$start + [cbs length] - 1}] 2124 set v(undoc) "snd cut $start $tmp" 2125 set v(redoc) "snd insert cbs $start" 2126 2127 PutMarker m2 [expr {$startt + [DTime2Time [cbs length -unit seconds]]}] 0 0 2128 set v(smpchanged) 1 2129 .tb.undo config -state normal 2130 DrawOverAxis 2131 Redraw 2132} 2133 2134proc SendXScroll {} { 2135 global c v 2136 2137 if $v(slink) { 2138 foreach prg [winfo interps] { 2139 if [regexp .*xs.* $prg] { 2140 if {[winfo name .] != $prg} { 2141 send $prg RecvXScroll [Coord2Time [expr [lindex [.cf.fc.xscroll get] 0] * $v(width)]] 2142 } 2143 } 2144 } 2145 } 2146} 2147 2148proc RecvXScroll {a} { 2149 global c v 2150 2151 set f [Time2Coord [expr double($a / $v(width))]] 2152 eval $c xview moveto $f 2153} 2154 2155proc Redraw {args} { 2156 global c labels f v 2157 2158 SetCursor watch 2159 set length [snd length] 2160 if {$args != "quick"} { 2161 $c delete obj 2162 $c config -bg $v(bg) 2163 .cf.fyc.yc config -bg $v(bg) 2164 .of.c config -bg $v(bg) 2165 if {$length == 0} { set length 1 } 2166 set v(endsmp) [expr $v(startsmp) + $v(rate) * $v(scrw) / $v(pps)] 2167 if {$v(endsmp) > $length} { 2168 set v(endsmp) $length 2169 } 2170 2171 if {[expr int(double($length * $v(pps)) / $v(rate))] < $v(scrw)} { 2172 if [winfo exist .of] { pack forget .of } 2173 set v(startsmp) 0 2174 set v(endsmp) $length 2175 } else { 2176 pack .of -side top -fill x -before .cf 2177 if {$::tcl_platform(platform) == "windows"} { 2178 DrawOverAxis 2179 } 2180 } 2181 .of.xscroll set [expr double($v(startsmp)) / $length] [expr double($v(endsmp)) / $length] 2182 2183 .cf.fyc.yc delete axis 2184 if {$v(waveh) > 0} { 2185 if {$v(linkfile) && $f(sndfile) != ""} { 2186 snack::deleteInvalidShapeFile [file tail $f(spath)$f(sndfile)] 2187 $c create waveform 0 0 -sound snd -height $v(waveh) \ 2188 -pixels $v(pps) -tags [list obj wave] \ 2189 -start $v(startsmp) -end $v(endsmp) \ 2190 -channel $v(vchan) -debug $::debug -fill $v(fg) \ 2191 -shapefile [file rootname [file tail $f(spath)$f(sndfile)]].shape\ 2192 -progress snack::progressCallback 2193 snack::makeShapeFileDeleteable [file tail $f(spath)$f(sndfile)] 2194 } else { 2195 $c create waveform 0 0 -sound snd -height $v(waveh) \ 2196 -pixels $v(pps) -tags [list obj wave] \ 2197 -start $v(startsmp) -end $v(endsmp) \ 2198 -channel $v(vchan) -debug $::debug -fill $v(fg) 2199 } 2200 $c lower wave 2201 .cf.fyc.yc create text $v(yaxisw) 2 -text [snd max]\ 2202 -font $v(sfont) -anchor ne -tags axis -fill $v(fg) 2203 .cf.fyc.yc create text $v(yaxisw) $v(waveh) -text [snd min]\ 2204 -font $v(sfont) -anchor se -tags axis -fill $v(fg) 2205 .cf.fyc.yc create line 0 [expr $v(waveh)+0] $v(yaxisw) \ 2206 [expr $v(waveh)+0] -tags axis -fill $v(fg) 2207 } 2208 if {$v(topfr) > [expr $v(rate)/2]} { 2209 set v(topfr) [expr $v(rate)/2] 2210 } 2211 if {$v(spegh) > 0} { 2212 set v(winlen) [expr int($v(rate) / $v(anabw))] 2213 if {$v(winlen) > $v(fftlen)} { 2214 set v(winlen) $v(fftlen) 2215 } 2216 $c create spectrogram 0 $v(waveh) -sound snd -fftlen $v(fftlen) \ 2217 -winlen $v(winlen) -height $v(spegh) -pixels $v(pps) \ 2218 -preemph $v(preemph) -topfr $v(topfr) -tags [list obj speg] \ 2219 -start $v(startsmp) -end $v(endsmp)\ 2220 -contrast $v(contrast) -brightness $v(brightness)\ 2221 -gridtspacing $v(gridtspacing) \ 2222 -gridfspacing $v(gridfspacing) -channel $v(vchan) \ 2223 -colormap $v($v(cmap)) -gridcol $v(gridcolor) \ 2224 -progress snack::progressCallback -debug $::debug 2225 $c lower speg 2226 snack::frequencyAxis .cf.fyc.yc 0 $v(waveh) $v(yaxisw) $v(spegh)\ 2227 -topfrequency $v(topfr) -tags axis -fill $v(fg)\ 2228 -font $v(sfont) 2229 .cf.fyc.yc create line 0 [expr $v(spegh) + $v(waveh)+0] \ 2230 $v(yaxisw) [expr $v(spegh) + $v(waveh)+0] -tags axis\ 2231 -fill $v(fg) 2232 } 2233 2234 set v(width) [expr int($v(pps) * double($v(endsmp) - $v(startsmp)) / $v(rate))] 2235 if {$v(width) == 0} { set v(width) 600 } 2236 $c create line 0 0 $v(width) 0 -tags obj -fill $v(fg) 2237 $c create line 0 $v(waveh) $v(width) $v(waveh) -tags obj -fill $v(fg) 2238 2239 } 2240 2241 $c delete tran axis 2242 set y [expr $v(waveh) + $v(spegh)] 2243 $c create line 0 $y $v(width) $y -tags axis -fill $v(fg) 2244 2245 snack::timeAxis $c 0 $y $v(width) $v(timeh) $v(pps)\ 2246 -tags axis -starttime [expr double($v(startsmp)) / $v(rate)]\ 2247 -fill $v(fg) -font $v(sfont) 2248 incr y $v(timeh) 2249 $c create line 0 $y $v(width) $y -tags axis -fill $v(fg) 2250 2251 .cf.fyc.yc configure -height $y 2252 set tlab t 2253 .cf.fyc.yc create text 5 [expr $v(waveh) + $v(spegh) + 2] -text $tlab \ 2254 -font $v(sfont) -anchor nw -tags axis -fill $v(fg) 2255 2256 if $v(ipa) { 2257 incr y [DrawLabels $y $labels ipa] 2258 } 2259 incr y [DrawLabels $y $labels lab] 2260 2261 foreach p $v(plugins) { 2262 incr y [namespace inscope $p Redraw $y] 2263 } 2264 2265 set v(toth) $y 2266 $c configure -height $v(toth) -width $v(width) -scrollregion "0 0 $v(width) $v(toth)" 2267 .cf.fyc.yc configure -height $v(toth) -scrollregion "0 0 $v(yaxisw) $v(toth)" 2268 2269# Someday in a perfect universe 2270 2271 if {$::tcl_platform(os) == "Linux" || \ 2272 $::tcl_platform(platform) == "macintosh"} { 2273 set maxw [lindex [wm maxsize .] 0] 2274 if {$v(width) > $maxw} { 2275 if [winfo exist .of] { 2276 . config -width $maxw -height [expr $v(toth) + 130] 2277 } else { 2278 . config -width $maxw -height [expr $v(toth) + 40] 2279 } 2280 pack propagate . 0 2281 } else { 2282 pack propagate . 1 2283 } 2284 } 2285 if {$::tcl_platform(platform) == "windows"} { 2286 set maxw [lindex [wm maxsize .] 0] 2287 if {$v(width) > $maxw} { 2288 if {[expr int(double($length * $v(pps)) / $v(rate))] >= $v(scrw)} { 2289 wm geometry . [expr $maxw - 15]x[expr $v(toth) + 120] 2290 } else { 2291 wm geometry . [expr $maxw - 15]x[expr $v(toth) + 70] 2292 } 2293 } 2294 } 2295 2296 catch {PutMarker m1 [Marker2Time m1] 0 0} 2297 catch {PutMarker m2 [Marker2Time m2] 0 0} 2298 SetCursor "" 2299} 2300 2301proc DrawLabels {y labels type} { 2302 global c v f ipa 2303 2304 if {[llength $labels] == 0} { 2305 return 0 2306 } else { 2307 $c create line 0 [expr $y + $v(labelh)] [expr $v(width) -1] \ 2308 [expr $y + $v(labelh)] -tags obj -fill $v(fg) 2309 set start 0 2310 set end 0 2311 set label "" 2312 set i 0 2313 foreach row $labels { 2314 switch $v(labfmt) { 2315 TIMIT - 2316 HTK { 2317 scan $row {%d %d %s} start end label 2318 set lx [Time2Coord $start] 2319# if {!$v(zerolabs) && $end == $start} continue 2320 } 2321 MIX { 2322 scan $row {%d %s} start label 2323 set lx [Time2Coord $start] 2324 set end [Coord2Time $v(width)] 2325 scan [lindex $labels [expr $i+1]] {%d} end 2326 } 2327 WAVES { 2328 scan $row {%f %d %s} end color label 2329 set lx [Time2Coord $end] 2330 set start 0 2331 scan [lindex $labels [expr $i-1]] {%f} start 2332 } 2333 } 2334 if {$lx >= 0 && $lx <= $v(width)} { 2335 if {$v(labalign) == "c"} { 2336 set tx [Time2Coord [expr ($start+$end)/2]] 2337 } elseif {$v(labalign) == "w"} { 2338 set tx [expr [Time2Coord $start] + 2] 2339 } else { 2340 set tx [Time2Coord $end] 2341 } 2342 if {$type == "lab"} { 2343 $c create text $tx [expr $y+12] -text $label\ 2344 -font $v(font) -anchor $v(labalign)\ 2345 -tags [list $i obj text lab$i tran] -fill $v(fg) 2346 $c create line $lx $y $lx [expr $y+$v(labelh)] \ 2347 -tags [list b$i obj bound tran] -fill $v(fg) 2348 } else { 2349 if {$v(labfmt) == "MIX"} { 2350 regsub -all {\$} $label "" t1 2351 regsub -all {\"} $t1 "" t2 2352 regsub -all # $t2 "" t3 2353 regsub -all {\`} $t3 "" t4 2354 regsub -all {\'} $t4 "" tmp 2355 set label $tmp 2356 } 2357# catch {$c create image $tx [expr $y+2] \ 2358# -image [image create photo -file $f(ipapath)/$ipa($label)] \ 2359# -anchor n -tags [list obj tran]} 2360 if {$::tcl_platform(platform) == "windows"} { 2361 $c create text $tx [expr $y+12] \ 2362 -text $label -font IPAKiel -fill $v(fg)\ 2363 -anchor $v(labalign) -tags [list obj tran] 2364 } else { 2365 catch {$c create bitmap $tx [expr $y+2] \ 2366 -bitmap @$f(ipapath)/$ipa($label) \ 2367 -anchor n -tags [list obj tran]} 2368 } 2369 $c create line $lx [expr $y] $lx [expr $y+$v(labelh)] \ 2370 -tags [list obj tran] -fill $v(fg) 2371 } 2372 } 2373 incr i 2374 } 2375 } 2376 return $v(labelh) 2377} 2378 2379proc ScrollCmd {args} { 2380 global v 2381 2382 if {[lindex $args 0] == "moveto"} { 2383 set delta [expr [lindex [.of.xscroll get] 1] - [lindex [.of.xscroll get] 0]] 2384 set pos [lindex $args 1] 2385 if {$pos < 0.0} { set pos 0.0 } 2386 if {$pos > [expr 1.0 - $delta]} { set pos [expr 1.0 - $delta] } 2387 .of.xscroll set $pos [expr $pos + $delta] 2388 } elseif {[lindex $args 0] == "scroll" && $v(scroll) == 1} { 2389 set pos [expr double($v(startsmp)) / [snd length]] 2390 set delta [expr double($v(endsmp)) / [snd length] - $pos] 2391 if {[lindex $args 1] > 0} { 2392 set pos [expr $pos + $delta] 2393 if {$pos > [expr 1.0 - $delta]} { set pos [expr 1.0 - $delta] } 2394 } 2395 if {[lindex $args 1] < 0} { 2396 set pos [expr $pos - $delta] 2397 if {$pos < 0.0} { set pos 0.0 } 2398 } 2399 .of.xscroll set $pos [expr $pos + $delta] 2400 set v(scroll) 0 2401 } 2402} 2403 2404proc RePos {args} { 2405 global v c 2406 2407 set v(startsmp) [expr int ([lindex [.of.xscroll get] 0] * [snd length])] 2408 set v(endsmp) [expr int ([lindex [.of.xscroll get] 1] * [snd length])] 2409 $c xview moveto 0 2410 Redraw 2411} 2412 2413proc DrawOverAxis {} { 2414 global v 2415 2416 set totw [winfo width .] 2417 set scrh [winfo height .of.xscroll] 2418 set width [expr $totw - 2 * $scrh] 2419 set length [snd length -unit seconds] 2420 if {$length > 0} { 2421 set v(opps) [expr $width/$length] 2422 } else { 2423 set v(opps) 400 2424 } 2425 .of.c delete overaxis 2426 snack::timeAxis .of.c $scrh 20 $width 11 $v(opps) -tags overaxis \ 2427 -fill $v(fg) 2428} 2429 2430proc OverPlay {x} { 2431 global v 2432 2433 set start [expr int($v(rate)*(($x - [winfo height .of.xscroll]) * 1000 / $v(opps)))] 2434 set end [snd length] 2435 Stop snd 2436 if {$start < 0} { set start 0 } 2437 set v(s0) $start 2438 set v(s1) $end 2439 Play snd $start $end 2440 .of.c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2441 after cancel PutPlayMarker 2442 after 50 PutPlayMarker 2443} 2444 2445proc Reconf {} { 2446 global c v f 2447 2448 set dox 0 2449 set doy 0 2450 if {[$c xview] == "0 1"} { set dox 1 } 2451 if {[$c yview] == "0 1"} { set doy 1 } 2452 2453 if {$dox} { 2454 pack forget .cf.fc.xscroll 2455 pack forget .cf.fyc.yc2 2456 } else { 2457 pack .cf.fc.xscroll -side bottom -fill x -before $c 2458 .cf.fyc.yc2 config -height [winfo height .cf.fc.xscroll] 2459 pack .cf.fyc.yc2 -side bottom -fill x -before .cf.fyc.yc 2460 } 2461 if {$doy} { 2462 pack forget .cf.fc.yscroll 2463 } else { 2464 pack .cf.fc.yscroll -side right -fill y -before $c 2465 } 2466 2467 set ww [.of.c itemcget overwave -width] 2468 set v(scrh) [winfo height .of.xscroll] 2469 set totw [expr [winfo width .] - 2 * $v(scrh)] 2470 if {$ww != $totw && ![catch {pack info .of}]} { 2471 .of.c delete overwave 2472 if {$v(linkfile) && $f(sndfile) != ""} { 2473 .of.c create waveform $v(scrh) 0 -sound snd -height 20 \ 2474 -width $totw -tags overwave -fill $v(fg) -debug $::debug \ 2475 -shapefile [file rootname [file tail $f(spath)$f(sndfile)]].shape 2476 } else { 2477 .of.c create waveform $v(scrh) 0 -sound snd -height 20 \ 2478 -width $totw -tags overwave -fill $v(fg) -debug $::debug 2479 } 2480 .of.c create rectangle -1 -1 -1 -1 -tags mark -fill yellow -stipple gray25 2481 } 2482 if {[snd length] > 0} DrawOverAxis 2483# if {$::tcl_platform(platform) == "unix"} { 2484# if {$v(propflag) > 1} { pack propagate . 0 } 2485# } 2486# if {$dox && $doy} { incr v(propflag) } 2487} 2488 2489proc SetMsg {msg args} { 2490 global v 2491 2492 if {$args == ""} { 2493 set v(msg) $msg 2494 .bf.lab config -state disabled 2495 } elseif {$args == "mark"} { 2496 set v(msg) $msg 2497 set v(currline) -1 2498 .bf.lab config -state normal 2499 } else { 2500 set v(msg) $msg 2501 set v(currline) $args 2502 .bf.lab config -state normal 2503 } 2504 SetCursor "" 2505} 2506 2507proc InputFromMsgLine {key} { 2508 global v labels 2509 2510 if {$key == "BackSpace"} return 2511 if {$v(currline) >= 0} { 2512 set labels [lreplace $labels $v(currline) $v(currline) $v(msg)] 2513 Redraw quick 2514 } else { 2515 if {[scan $v(msg) {From: %s to: %s length: %s ( %f - %f , %f} t0 t1 t2 t3 t4 t5] == 6} { 2516 if {$t0 != [lindex $v(fromto) 0]} { 2517 PutMarker m1 $t0 0 0 2518 } 2519 if {$t1 != [lindex $v(fromto) 1]} { 2520 set t2 [expr $t1-$t0] 2521 PutMarker m2 $t1 0 0 2522 } 2523 if {$t2 != [lindex $v(fromto) 2]} { 2524 set t1 [expr $t0+$t2] 2525 PutMarker m2 $t1 0 0 2526 } 2527 if {$t3 != [lindex $v(fromto) 3]} { 2528 set t0 [DTime2Time $t3] 2529 PutMarker m1 $t0 0 0 2530 } 2531 if {$t4 != [lindex $v(fromto) 4]} { 2532 set t1 [expr [DTime2Time $t4]-[DTime2Time $t3]] 2533 PutMarker m2 [DTime2Time $t4] 0 0 2534 } 2535 if {$t5 != [lindex $v(fromto) 5]} { 2536 set t1 [expr [DTime2Time $t3]+[DTime2Time $t5]] 2537 PutMarker m2 $t1 0 0 2538 } 2539 set t3 [format "%.3f" [Time2DTime $t0]] 2540 set t4 [format "%.3f" [Time2DTime $t1]] 2541 set t5 [format "%.3f" [expr $t4 - $t3]] 2542 SetMsg [format "From: %9s to: %9s length: %9s\t(%.3f - %.3f, %.3f)"\ 2543 $t0 $t1 $t2 $t3 $t4 $t5] mark 2544 set v(fromto) [list $t0 $t1 $t2 $t3 $t4 $t5] 2545 } 2546 } 2547} 2548 2549proc PlayToCursor {x} { 2550 global c f v 2551 2552 Stop snd 2553 if {[snd length] == 0} return 2554 set start [Marker2Sample m1] 2555 set s [Coord2Sample [$c canvasx $x]] 2556 if {$s < $start} { 2557 set end $start 2558 set start $s 2559 } else { 2560 set end $s 2561 } 2562 SetMsg "Playing range: $start $end" 2563 set v(s0) $start 2564 set v(s1) $end 2565 Play snd $start $end 2566 set v(pause) 0 2567 .of.c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2568 $c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2569 after 50 PutPlayMarker 2570} 2571 2572proc PlayMark {args} { 2573 global c f v 2574 2575 Stop snd 2576 if {[snd length] == 0} return 2577 set start [Marker2Sample m1] 2578 set end [Marker2Sample m2] 2579 if {$start > [snd length]} return 2580 if {[llength $args] > 0} { 2581 set x [Coord2Sample [$c canvasx [lindex $args 0]]] 2582 if {$x < $start} { 2583 set end $start 2584 set start 0 2585 } 2586 if {$x > $end} { 2587 set start $end 2588 set end [snd length] 2589 } 2590 } 2591 if {$start == $end} { 2592 set start $end 2593 set end [snd length] 2594 } 2595 SetMsg "Playing range: $start $end" 2596 set v(s0) $start 2597 set v(s1) $end 2598 Play snd $start $end 2599 set v(pause) 0 2600 .of.c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2601 $c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2602 after 50 PutPlayMarker 2603} 2604 2605proc PlayAll {} { 2606 global c v 2607 2608 Stop snd 2609 SetMsg "Playing all samples" 2610 set v(s0) 0 2611 set v(s1) [snd length] 2612 Play snd 2613 set v(pause) 0 2614 .of.c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2615 $c create poly -1 -1 -1 -1 -1 -1 -fill red -tags playmark 2616 after 50 PutPlayMarker 2617} 2618 2619proc Play {s {start 0} {end -1}} { 2620 global v 2621 2622 if !$v(remote) { 2623 $s play -start $start -end $end 2624 } else { 2625 set sock [socket $v(ashost) $v(asport)] 2626 if {$end == -1} { 2627 set end [snd length] 2628 } 2629 set v(rp_s) $s 2630 set v(rp_sock) $sock 2631 set end2 $end 2632 if {$end2 > [expr $start + 10000]} { 2633 set end2 [expr $start + 10000] 2634 } 2635 set v(rp_next) $end2 2636 set v(rp_end) $end 2637 fconfigure $sock -translation binary -blocking 0 2638 puts -nonewline $sock play 2639 flush $sock 2640 set handle [gets $sock] 2641 set v(handle) $handle 2642 puts -nonewline $sock [$s data -fileformat au -start $start -end $end2] 2643 fileevent $sock writable PlayHandler 2644 } 2645} 2646 2647proc PlayHandler {} { 2648 global v 2649 2650 if {$v(rp_next) < $v(rp_end)} { 2651 set end2 $v(rp_end) 2652 if {$end2 > [expr $v(rp_next) + 10000]} { 2653 set end2 [expr $v(rp_next) + 10000] 2654 } 2655 puts -nonewline $v(rp_sock) [$v(rp_s) data -fileformat raw -start $v(rp_next) -end $end2 -byteorder bigEndian] 2656 set v(rp_next) $end2 2657 } else { 2658 close $v(rp_sock) 2659 } 2660} 2661 2662proc Stop {s} { 2663 global v 2664 2665 if !$v(remote) { 2666 $s stop 2667 } else { 2668 catch {close $v(rp_sock)} 2669 catch {set sock [socket $v(ashost) $v(asport)]} 2670 if ![info exists sock] return 2671 fconfigure $sock -translation binary 2672 puts -nonewline $sock stop 2673 puts $sock $v(handle) 2674 close $sock 2675 } 2676} 2677 2678proc StopPlay {} { 2679 global c v 2680 2681 after cancel PutPlayMarker 2682 Stop snd 2683 set v(pause) 0 2684 set v(s1) 0 2685 .of.c delete playmark 2686 $c delete playmark 2687 if $v(activerec) { 2688 after cancel UpdateRec 2689 Redraw 2690 event generate .cf.fc.c <Configure> 2691 MarkAll 2692 set v(activerec) 0 2693 } 2694} 2695 2696proc PausePlay {} { 2697 global c v 2698 2699 if $v(activerec) { 2700 snd pause 2701 return 2702 } 2703 set v(pause) [expr 1 - $v(pause)] 2704 if $v(pause) { 2705 after cancel PutPlayMarker 2706 set v(s0) [expr $v(s0) + int([snack::audio elapsedTime] * $v(rate))] 2707 Stop snd 2708 } else { 2709 after 50 PutPlayMarker 2710 Play snd $v(s0) $v(s1) 2711 } 2712} 2713 2714proc PutPlayMarker {} { 2715 global v c 2716 2717 if $v(pause) return 2718 2719 set time [expr [snack::audio elapsedTime] + double($v(s0)) / $v(rate)] 2720 if {$time > [expr double($v(s1)) / $v(rate)] || ![snack::audio active]} { 2721 .of.c delete playmark 2722 $c delete playmark 2723 return 2724 } 2725 SetMsg "Playing at [format "%.2f" $time]" 2726 set ox [expr $v(scrh) + $time * $v(opps) / 1000.0] 2727 set x [expr ($time - double($v(startsmp)) / $v(rate)) * $v(pps)] 2728 set y [expr $v(waveh) + $v(spegh) + 4] 2729 .of.c coords playmark $ox 22 [expr $ox-5] 30 [expr $ox+5] 30 2730 $c coords playmark $x $y [expr $x-5] [expr $y+10] [expr $x+5] [expr $y+10] 2731 update idletasks 2732 after 50 PutPlayMarker 2733} 2734 2735proc InfoStr {arg} { 2736 global f v labels 2737 2738 set samps [snd length] 2739 set time [snd length -unit seconds] 2740 if {$arg == "path"} { 2741 set snd "$f(spath)$f(sndfile)" 2742 set lab "$f(lpath)$f(labfile)" 2743 } else { 2744 set snd $f(sndfile) 2745 set lab $f(labfile) 2746 } 2747 set info [format "Sample file: %s (%s) %d samples %.2f seconds" $snd $v(smpfmt) $samps $time] 2748 if {$labels != {}} { 2749 set info "$info Label file: $lab ($v(labfmt))" 2750 } 2751 return $info 2752} 2753 2754proc xsGetGeometry {} { 2755 scan [wm geometry .] "%dx%d+%d+%d" w h x y 2756 if {$::tcl_platform(platform) == "windows"} { 2757 return +$x+[expr $y+$h+40] 2758 } else { 2759 return +$x+[expr $y+$h+68] 2760 } 2761} 2762 2763proc ToggleSpeg {} { 2764 global v 2765 2766 if [snack::audio active] return 2767 if $v(showspeg) { 2768 set v(spegh) $v(remspegh) 2769 } else { 2770 set v(remspegh) $v(spegh) 2771 set v(spegh) 0 2772 } 2773 Redraw 2774} 2775 2776proc ToggleRecording {} { 2777 global v 2778 2779 if $v(recording) { 2780 .tb.rec config -state normal 2781 } else { 2782 .tb.rec config -state disabled 2783 } 2784 2785} 2786 2787proc Record {} { 2788 global c v rec 2789 2790 StopPlay 2791 set v(smpchanged) 1 2792 if [winfo exist .of] { pack forget .of } 2793 $c delete obj 2794 .of.c delete overwave 2795 set width [winfo width $c] 2796 $c xview moveto 0 2797 if {$v(waveh) > 0} { 2798 $c create waveform 0 0 -sound snd -height $v(waveh) -pixels $v(pps) \ 2799 -width $width -tags [list obj recwave] -channel $v(vchan) \ 2800 -debug $::debug -fill red 2801 } 2802 if {$v(spegh) > 0} { 2803 $c create spectrogram 0 $v(waveh) -sound snd -height $v(spegh) \ 2804 -pixels $v(pps) \ 2805 -width $width -tags [list obj recwave] -channel $v(vchan) \ 2806 -colormap $v($v(cmap)) -debug $::debug 2807 } 2808 if {$v(linkfile)} { 2809 catch {file delete -force _xs[pid].wav} 2810 snd configure -file _xs[pid].wav 2811 } 2812 snd record 2813 set v(activerec) 1 2814 after 100 UpdateRec 2815} 2816 2817proc UpdateRec {} { 2818 global c v 2819 2820 if {$v(activerec) == 0} return 2821 set secs [expr int([snd length -unit seconds])] 2822 set dec [format "%.2d" [expr int(100*([snd length -unit seconds] - $secs))]] 2823 set time [clock format $secs -format "Length: %M:%S.$dec"] 2824# if {$secs > 9} { 2825# $c delete recwave rectext 2826# $c create text [expr [lindex [$c xview] 0] * $v(width) + 60] 20 \ 2827# -fill red -text $time -tags [list obj rectext] 2828# update 2829# } 2830 SetMsg $time 2831 after 100 UpdateRec 2832} 2833 2834proc MoveBoundary {x} { 2835 global c labels v 2836 2837 set coords [$c coords current] 2838 set x [$c canvasx $x] 2839 if {$x < 0} { set x 0 } 2840 set i [string trim [lindex [$c gettags current] 0] b] 2841 if [string match [$c type current] text] return 2842 if {$i == "obj" || $i == "mark" || $i == "axis" || $i == ""} { 2843 return 2844 } 2845 2846 set h [expr $i - 1] 2847 set j [expr $i + 1] 2848 2849 if {$v(lastmoved) != $i} { 2850 set v(labchanged) 1 2851 SetUndo $labels 2852 set v(lastmoved) $i 2853 } 2854 2855 $c raise current 2856 set px 0 2857 set nx $v(width) 2858 set pb [$c find withtag b$h] 2859 set nb [$c find withtag b$j] 2860 if {$pb != ""} { set px [lindex [$c coords $pb] 0]} 2861 if {$nb != ""} { set nx [lindex [$c coords $nb] 0]} 2862 2863 if {$x <= $px} { set x [expr $px + 1] } 2864 if {$nx <= $x} { set x [expr $nx - 1] } 2865 2866 $c coords current $x [lindex $coords 1] $x [lindex $coords 3] 2867 set rest "" 2868 2869 switch $v(labfmt) { 2870 TIMIT - 2871 HTK { 2872 scan [lindex $labels $i] {%d %d %s %[^�]} start stop label rest 2873 if {$j == [llength $labels]} { set length [expr $stop - $start] } 2874 set start [Coord2Time $x] 2875 if {$j == [llength $labels]} { set stop [expr $start + $length] } 2876 set labels [lreplace $labels $i $i "$start\n$stop\n$label\n$rest"] 2877 if {$h <= 0} return 2878 while {[lindex [lindex $labels $h] 0] == [lindex [lindex $labels $h] 1]} { 2879 set hlabel [lindex [lindex $labels $h] 2] 2880 set hrest [lindex [lindex $labels $h] 3] 2881 set labels [lreplace $labels $h $h "$start\n$start\n$hlabel\n$hrest"] 2882 incr h -1 2883 } 2884 set rest "" 2885 scan [lindex $labels $h] {%d %d %s %[^�]} start stop label rest 2886 if {$v(labfmt) == "HTK"} { 2887 set stop [expr [Coord2Time $x]-(10000000/$v(rate))] 2888 } else { 2889 set stop [Coord2Time $x] 2890 } 2891 set labels [lreplace $labels $h $h "$start\n$stop\n$label\n$rest"] 2892 } 2893 MIX { 2894 scan [lindex $labels $i] {%d %s %[^�]} start label rest 2895 set start [Coord2Time $x] 2896 set labels [lreplace $labels $i $i "$start\n$label\n$rest"] 2897 } 2898 WAVES { 2899 scan [lindex $labels $i] {%f %d %s %[^�]} end color label rest 2900 set end [Coord2Time $x] 2901 set labels [lreplace $labels $i $i "$end\n$color\n$label\n$rest"] 2902 } 2903 } 2904 SetMsg [Coord2Time $x] 2905} 2906 2907proc SetLabelText {i label} { 2908 global labels v 2909 2910 set rest "" 2911 switch $v(labfmt) { 2912 TIMIT - 2913 HTK { 2914 scan [lindex $labels $i] {%d %d %s %[^�]} start stop junk rest 2915 set labels [lreplace $labels $i $i "$start\n$stop\n$label\n$rest"] 2916 } 2917 MIX { 2918 scan [lindex $labels $i] {%d %s %[^�]} start junk rest 2919 set labels [lreplace $labels $i $i "$start\n$label\n$rest"] 2920 } 2921 WAVES { 2922 scan [lindex $labels $i] {%f %d %s %[^�]} end color junk rest 2923 set labels [lreplace $labels $i $i "$end\n$color\n$label\n$rest"] 2924 } 2925 } 2926} 2927 2928proc Undo {} { 2929 global c v labels undo 2930 2931 if {[cbs length] != 0} { 2932 eval $v(undoc) 2933 foreach {v(undoc) v(redoc)} [list $v(redoc) $v(undoc)] break 2934 DrawOverAxis 2935 Redraw 2936 } else { 2937 foreach {labels undo} [list $undo $labels] break 2938 Redraw quick 2939 } 2940 SetMsg "" 2941} 2942 2943proc SetUndo {l} { 2944 global undo 2945 2946 set undo $l 2947 .tb.undo config -state normal 2948} 2949 2950proc MarkAll {} { 2951 global v 2952 2953 PutMarker m1 0 0 0 2954 PutMarker m2 [Coord2Time $v(width)] 0 0 2955} 2956 2957proc ZeroXAdjust {} { 2958 global v 2959 2960 foreach m {m1 m2} { 2961 set start [Marker2Sample $m] 2962 snd sample [expr $start-100] ;# to fill sample buffer with leftmost 2963 for {set i 0} {$i < 100} {incr i} { 2964 set j [expr {$start + $i}] 2965 if {$j >= [snd length]} break 2966 if {$v(vchan) == 1} { 2967 set sample [lindex [snd sample $j] 1] 2968 set psample [lindex [snd sample [expr {$j-1}]] 1] 2969 } else { 2970 set sample [lindex [snd sample $j] 0] 2971 set psample [lindex [snd sample [expr {$j-1}]] 0] 2972 } 2973 if {[expr {$sample*$psample}] < 0} break 2974 set j [expr {$start - $i}] 2975 if {$j < 0} break 2976 if {$v(vchan) == 1} { 2977 set sample [lindex [snd sample $j] 1] 2978 set psample [lindex [snd sample [expr {$j-1}]] 1] 2979 } else { 2980 set sample [lindex [snd sample $j] 0] 2981 set psample [lindex [snd sample [expr {$j-1}]] 0] 2982 } 2983 if {[expr {$sample*$psample}] < 0} break 2984 } 2985 if {$i < 100} { 2986 PutMarker $m [Sample2Time $j] 0 0 2987 } 2988 2989 } 2990 # Copied from PutMarker 2991 DrawZoom 1 2992 DrawSect 2993 set t1 [Marker2Time m1] 2994 set t2 [Marker2Time m2] 2995 set l [expr $t2 - $t1] 2996 set tt1 [Time2DTime $t1] 2997 set tt2 [Time2DTime $t2] 2998 set ll [expr $tt2 - $tt1] 2999 SetMsg [format "From: %9s to: %9s length: %9s\t(%.3f - %.3f, %.3f)"\ 3000 $t1 $t2 $l $tt1 $tt2 $ll] mark 3001 set v(fromto) [list $t1 $t2 $l $tt1 $tt2 $ll] 3002} 3003 3004proc InsertLabel {x y} { 3005 global c v labels 3006 3007 set v(labchanged) 1 3008 SetUndo $labels 3009 InsertLabelEntry [Coord2Time [$c canvasx $x]] 3010 3011 $c delete bound text 3012 Redraw quick 3013} 3014 3015proc InsertLabelEntry {t} { 3016 global labels v 3017 3018 set i 0 3019 switch $v(labfmt) { 3020 TIMIT - 3021 HTK { 3022 foreach l $labels { 3023 if {([lindex $l 0] < $t) && ([lindex $l 1] > $t)} { break } 3024 incr i 3025 } 3026 if {[llength $labels] == $i} { incr i -1 } 3027 if {$labels == ""} { 3028 set sto [DTime2Time [snd length -unit seconds]] 3029 set labels [list "$t\n$sto\nx"] 3030 } elseif {$t < [lindex [lindex $labels 0] 0]} { 3031 set sto [lindex [lindex $labels 0] 0] 3032 set labels [linsert $labels 0 "$t\n$sto\nx"] 3033 } elseif {[llength $labels] == [expr $i+1]} { 3034 set sta1 [lindex [lindex $labels $i] 0] 3035 set sto1 $t 3036 set lab1 [lindex [lindex $labels $i] 2] 3037 set sta2 $t 3038 set sto2 [lindex [lindex $labels $i] 1] 3039 set lab2 x 3040 set labels [lreplace $labels $i $i "$sta1\n$sto1\n$lab1" "$sta2\n$sto2\n$lab2"] 3041 } else { 3042 SetMsg [lindex [lindex $labels $i] 2] 3043 set sta1 [lindex [lindex $labels $i] 0] 3044 set sto1 $t 3045 set lab1 [lindex [lindex $labels $i] 2] 3046 set sta2 $t 3047 set sto2 [lindex [lindex $labels [expr $i+1]] 0] 3048 set lab2 x 3049 set labels [lreplace $labels $i $i "$sta1\n$sto1\n$lab1" "$sta2\n$sto2\n$lab2"] 3050 } 3051 } 3052 MIX { 3053 foreach l $labels { 3054 if {[lindex $l 0] > $t} { break } 3055 incr i 3056 } 3057 SetMsg [lindex [lindex $labels $i] 1] 3058 set labels [linsert $labels $i "$t\nx"] 3059 } 3060 WAVES { 3061 foreach l $labels { 3062 if {[lindex $l 0] > $t} { break } 3063 incr i 3064 } 3065 SetMsg [lindex [lindex $labels $i] 1] 3066 set labels [linsert $labels $i "$t\n121\nx"] 3067 } 3068 } 3069} 3070 3071proc DeleteLabel {x y} { 3072 global c v labels 3073 3074 set v(labchanged) 1 3075 SetUndo $labels 3076 if {[string compare [lindex [$c gettags [$c find closest\ 3077 [$c canvasx $x] [$c canvasy $y]]] 2] text] == 0} { 3078 set i [lindex [$c gettags [$c find closest\ 3079 [$c canvasx $x] [$c canvasy $y]]] 0] 3080 RemoveLabelEntry $i 3081 3082 $c delete bound text 3083 Redraw quick 3084 } 3085} 3086 3087proc RemoveLabelEntry {i} { 3088 global labels v 3089 3090 switch $v(labfmt) { 3091 TIMIT - 3092 HTK { 3093 set start [lindex [lindex $labels [expr $i-1]] 0] 3094 set stop [lindex [lindex $labels $i] 1] 3095 set label [lindex [lindex $labels [expr $i-1]] 2] 3096 set labels [lreplace $labels [expr $i-1] $i "$start\n$stop\n$label"] 3097 } 3098 WAVES - 3099 MIX { 3100 set labels [lreplace $labels $i $i] 3101 } 3102 } 3103} 3104 3105# if called by clicking on the text of a label, this label will be aligned to 3106# the selection 3107# FIXME: but this isn't foolproofed because if there is another label between 3108# the one to change and the selection only the selected label 3109# (and with HTK-format the right neighbour) will be changed ... 3110 3111proc AlignLabel {x y} { 3112 global c v labels 3113 3114 set v(labchanged) 1 3115 SetUndo $labels 3116 if {[string compare [lindex [$c gettags [$c find closest\ 3117 [$c canvasx $x] [$c canvasy $y]]] 2] text] == 0} { 3118 set i [lindex [$c gettags [$c find closest\ 3119 [$c canvasx $x] [$c canvasy $y]]] 0] 3120 3121 SetUndo $labels 3122 set start [Marker2Time m1] 3123 set end [Marker2Time m2] 3124 set rest "" 3125 3126 switch $v(labfmt) { 3127 TIMIT - 3128 HTK { 3129 scan [lindex $labels $i] {%d %d %s %[^�]} junk junk label rest 3130 set labels [lreplace $labels $i $i "$start\n$end\n$label\n$rest"] 3131 set rest "" 3132 set j [expr $i-1] 3133 if {$j >= 0} { 3134 scan [lindex $labels $j] {%d %d %s %[^�]} st junk label rest 3135 set labels [lreplace $labels $j $j "$st\n$start\n$label\n$rest"] 3136 } 3137 set rest "" 3138 set j [expr $i+1] 3139 if {$j < [llength $labels]} { 3140 scan [lindex $labels $j] {%d %d %s %[^�]} junk st label rest 3141 set labels [lreplace $labels $j $j "$end\n$st\n$label\n$rest"] 3142 } 3143 } 3144 MIX { 3145 scan [lindex $labels $i] {%d %s %[^�]} junk label rest 3146 set labels [lreplace $labels $i $i "$start\n$label\n$rest"] 3147 set rest "" 3148 set j [expr $i+1] 3149 catch {scan [lindex $labels $j] {%d %s %[^�]} junk label rest} 3150 catch {set labels [lreplace $labels $j $j "$end\n$label\n$rest"]} 3151 } 3152 WAVES { 3153 scan [lindex $labels $i] {%f %d %s %[^�]} junk color label rest 3154 set labels [lreplace $labels $i $i "$end\n$color\n$label\n$rest"] 3155 set rest "" 3156 set j [expr $i-1] 3157 if {$j >= 0} { 3158 scan [lindex $labels $j] {%f %d %s %[^�]} junk color label rest 3159 set labels [lreplace $labels $j $j "$start\n$color\n$label\n$rest"] 3160 } 3161 } 3162 } 3163 3164 $c delete bound text 3165 Redraw quick 3166 } else { 3167 puts "AlignLabel error: x=$x; y=$y" 3168 } 3169} 3170 3171proc CropLabels {cstart cend} { 3172 global labels v 3173 3174 set l {} 3175 switch $v(labfmt) { 3176 TIMIT - 3177 HTK { 3178 foreach row $labels { 3179 set rest "" 3180 scan $row {%d %d %s %[^�]} start stop label rest] 3181 if {$cend < $start} { 3182 } elseif {$cend > $start && $cend < $stop} { 3183 set start [expr $start - $cstart] 3184 set stop [expr $cend - $cstart] 3185 lappend l "$start\n$stop\n$label\n$rest" 3186 } elseif {$cstart > $start && $cstart < $stop} { 3187 set start 0 3188 set stop [expr $stop - $cstart] 3189 lappend l "$start\n$stop\n$label\n$rest" 3190 } elseif {$cstart < $start} { 3191 set start [expr $start - $cstart] 3192 set stop [expr $stop - $cstart] 3193 lappend l "$start\n$stop\n$label\n$rest" 3194 } 3195 } 3196 } 3197 MIX { 3198 foreach row $labels { 3199 set rest "" 3200 scan $row {%d %s %[^�]} start label rest 3201 if {$cend < $start} { 3202 } elseif {$cstart > $start} { 3203 set l [list "0\n$label\n$rest"] 3204 } elseif {$cstart < $start} { 3205 set start [expr $start - $cstart] 3206 lappend l "$start\n$label\n$rest" 3207 } 3208 } 3209 } 3210 WAVES { 3211 set flag 0 3212 foreach row $labels { 3213 set rest "" 3214 scan $row {%f %d %s %[^�]} end color label rest 3215 if {$cend < $end && $flag} { 3216 set end [expr $cend - $cstart] 3217 lappend l "$end\n$color\n$label\n$rest" 3218 break 3219 } 3220 if {$cstart < $end} { 3221 set end [expr $end - $cstart] 3222 lappend l "$end\n$color\n$label\n$rest" 3223 set flag 1 3224 } 3225 } 3226 } 3227 } 3228 return $l 3229} 3230 3231# moves the startpoint of the right label to the cursorposition 3232 3233proc GetRightLabel {x y} { 3234 global c labels v 3235 3236 set t [Coord2Time [$c canvasx $x]] 3237 set i 0 3238 set v(labchanged) 1 3239 SetUndo $labels 3240 set rest "" 3241 switch $v(labfmt) { 3242 TIMIT - 3243 HTK { 3244 foreach l $labels { 3245 if {$t < [lindex $l 0]} { break } 3246 if {([lindex $l 0] < $t) && ([lindex $l 1] > $t)} { break } 3247 incr i 3248 } 3249 if {[llength $labels] <= [expr $i+1]} return 3250 if {$t < [lindex [lindex $labels 0] 0]} { 3251 set sto [lindex [lindex $labels 0] 1] 3252 set lab [lindex [lindex $labels 0] 2] 3253 set labels [lreplace $labels 0 0 "$t\n$sto\n$lab"] 3254 } elseif {[llength $labels] == [expr $i-1]} { 3255 set sta1 [lindex [lindex $labels $i] 0] 3256 set sto1 $t 3257 set lab1 [lindex [lindex $labels $i] 2] 3258 set labels [lreplace $labels $i $i "$sta1\n$sto1\n$lab1"] 3259 SetMsg [lindex [lindex $labels $i] 2] 3260 } else { 3261 set sta1 [lindex [lindex $labels $i] 0] 3262 set sto1 $t 3263 set lab1 [lindex [lindex $labels $i] 2] 3264 set sta2 $t 3265 set sto2 [lindex [lindex $labels [expr $i+1]] 1] 3266 set lab2 [lindex [lindex $labels [expr $i+1]] 2] 3267 set labels [lreplace $labels $i [expr $i+1] "$sta1\n$sto1\n$lab1" "$sta2\n$sto2\n$lab2"] 3268 SetMsg [lindex [lindex $labels $i] 2] 3269 } 3270 } 3271 MIX { 3272 foreach l $labels { 3273 if {[lindex $l 0] > $t} { break } 3274 incr i 3275 } 3276 if {$i == [llength $labels]} return 3277 scan [lindex $labels $i] {%d %s %[^�]} junk label rest 3278 set labels [lreplace $labels $i $i "$t\n$label\n$rest"] 3279 SetMsg [lindex [lindex $labels $i] 1] 3280 } 3281 WAVES { 3282 foreach l $labels { 3283 if {([lindex $l 0] > $t)} { break } 3284 incr i 3285 } 3286 if {$i == [llength $labels]} return 3287 scan [lindex $labels $i] {%f %d %s %[^�]} junk color label rest 3288 set labels [lreplace $labels $i $i "$t\n$color\n$label\n$rest"] 3289 SetMsg [lindex [lindex $labels $i] 1] 3290 } 3291 } 3292 $c delete bound text 3293 Redraw quick 3294} 3295 3296proc PlayLabel {x y} { 3297 global c labels v 3298 3299 set t [Coord2Time [$c canvasx $x]] 3300 set i 0 3301 switch $v(labfmt) { 3302 TIMIT - 3303 HTK { 3304 foreach l $labels { 3305 if {([lindex $l 0] < $t) && ([lindex $l 1] > $t)} { break } 3306 incr i 3307 } 3308 if {[llength $labels] == $i} { incr i -1 } 3309 } 3310 MIX { 3311 foreach l $labels { 3312 if {[lindex $l 0] > $t} { break } 3313 incr i 3314 } 3315 incr i -1 3316 } 3317 WAVES { 3318 foreach l $labels { 3319 if {[lindex $l 0] > $t} { break } 3320 incr i 3321 } 3322 } 3323 } 3324 PlayNthLab $i 3325} 3326 3327proc PlayNthLab {n} { 3328 global labels v 3329 3330 switch $v(labfmt) { 3331 TIMIT - 3332 HTK { 3333 set start [lindex [lindex $labels $n] 0] 3334 set stop [lindex [lindex $labels $n] 1] 3335 Play snd [Time2Sample $start] [Time2Sample $stop] 3336 } 3337 MIX { 3338 set start [lindex [lindex $labels $n] 0] 3339 if {$n == -1} { set start 0 } 3340 catch {set stop [lindex [lindex $labels [expr $n + 1]] 0]} 3341 if {$stop == ""} { set stop [Coord2Time $v(width)] } 3342 Play snd [Time2Sample $start] [Time2Sample $stop] 3343 } 3344 WAVES { 3345 set start [lindex [lindex $labels [expr $n - 1]] 0] 3346 if {$start == ""} { set start 0 } 3347 set stop [lindex [lindex $labels $n] 0] 3348 Play snd [Time2Sample $start] [Time2Sample $stop] 3349 } 3350 } 3351} 3352 3353proc MarkLabel {x y} { 3354 global c labels v 3355 3356 set t [Coord2Time [$c canvasx $x]] 3357 set i 0 3358 switch $v(labfmt) { 3359 TIMIT - 3360 HTK { 3361 foreach l $labels { 3362 if {([lindex $l 0] < $t) && ([lindex $l 1] > $t)} { break } 3363 incr i 3364 } 3365 if {[llength $labels] == $i} { incr i -1 } 3366 } 3367 MIX { 3368 foreach l $labels { 3369 if {[lindex $l 0] > $t} { break } 3370 incr i 3371 } 3372 incr i -1 3373 } 3374 WAVES { 3375 foreach l $labels { 3376 if {[lindex $l 0] > $t} { break } 3377 incr i 3378 } 3379 } 3380 } 3381 MarkNthLab $i 3382} 3383 3384proc MarkNthLab {n} { 3385 global labels v 3386 3387 switch $v(labfmt) { 3388 TIMIT - 3389 HTK { 3390 set start [lindex [lindex $labels $n] 0] 3391 set stop [lindex [lindex $labels $n] 1] 3392 } 3393 MIX { 3394 set start [lindex [lindex $labels $n] 0] 3395 if {$n == -1} { set start 0 } 3396 catch {set stop [lindex [lindex $labels [expr $n + 1]] 0]} 3397 if {$stop == ""} { set stop [Coord2Time $v(width)] } 3398 } 3399 WAVES { 3400 set start [lindex [lindex $labels [expr $n - 1]] 0] 3401 if {$start == ""} { set start 0 } 3402 set stop [lindex [lindex $labels $n] 0] 3403 } 3404 default { 3405 puts "Wrong Labelformat $v(labfmt)" 3406 return 3407 } 3408 } 3409 # cause the left marker is always m1 we have to move the marker 3410 # in the right order 3411 if {$start > [Marker2Time m2]} { 3412 PutMarker m2 $stop 0 0 3413 SendPutMarker m2 [Time2Coord $stop] 3414 PutMarker m1 $start 0 0 3415 SendPutMarker m1 [Time2Coord $start] 3416 } else { 3417 PutMarker m1 $start 0 0 3418 SendPutMarker m1 [Time2Coord $start] 3419 PutMarker m2 $stop 0 0 3420 SendPutMarker m2 [Time2Coord $stop] 3421 } 3422} 3423 3424 3425proc SetRaw {} { 3426 global v 3427 3428 StopPlay 3429 set v(smpchanged) 1 3430 snd config -rate $v(rate) -encoding $v(sfmt) -channels $v(chan) 3431 Redraw 3432 Reconf 3433} 3434 3435proc Convert {encoding rate channels} { 3436 global v c 3437 3438 SetCursor watch 3439 StopPlay 3440 $c delete speg wave 3441 cbs copy snd 3442 if [catch { 3443 if {$rate != ""} { 3444 SetMsg "Converting sample rate [snd cget -rate] -> $rate" 3445 snd convert -rate $rate -progress snack::progressCallback 3446 set v(rate) [snd cget -rate] 3447 set v(undoc) "snd copy cbs" 3448 set v(redoc) "snd convert -rate $rate -progress snack::progressCallback" 3449 } 3450 if {$encoding != ""} { 3451 SetMsg "Converting sample encoding [snd cget -encoding] -> $encoding" 3452 snd convert -encoding $encoding -progress snack::progressCallback 3453 set v(sfmt) [snd cget -encoding] 3454 set v(undoc) "snd copy cbs" 3455 set v(redoc) "snd convert -encoding $encoding -progress snack::progressCallback" 3456 } 3457 if {$channels != ""} { 3458 SetMsg "Converting number of channels [snd cget -channels] -> $channels" 3459 snd convert -channels $channels -progress snack::progressCallback 3460 set v(chan) [snd cget -channels] 3461 set v(undoc) "snd copy cbs" 3462 set v(redoc) "snd convert -channels $channels -progress snack::progressCallback" 3463 } 3464 }] { 3465 SetMsg "Convert cancelled" 3466 } 3467 3468 Redraw 3469 set v(smpchanged) 1 3470 .tb.undo config -state normal 3471} 3472 3473proc Time2Sample {t} { 3474 global v 3475 3476 switch $v(labfmt) { 3477 HTK { 3478 expr {int($t/(10000000/$v(rate)))} 3479 } 3480 TIMIT - 3481 MIX { 3482 expr {int($t)} 3483 } 3484 WAVES { 3485 expr {int($t*$v(rate))} 3486 } 3487 } 3488} 3489 3490proc Sample2Time {s} { 3491 global v 3492 3493 switch $v(labfmt) { 3494 HTK { 3495 expr {int($s*(10000000.0/$v(rate)))} 3496 } 3497 TIMIT - 3498 MIX { 3499 set s 3500 } 3501 WAVES { 3502 expr {double($s)/$v(rate)} 3503 } 3504 } 3505} 3506 3507proc TimeRound {t} { 3508 global v 3509 3510 switch $v(labfmt) { 3511 HTK - 3512 TIMIT - 3513 MIX { 3514 expr {int($t)} 3515 } 3516 WAVES { 3517 expr {$t} 3518 } 3519 } 3520} 3521 3522proc Time2Coord {t} { 3523 global v 3524 3525 switch $v(labfmt) { 3526 HTK { 3527 expr {(($t-10000000*(double($v(startsmp))/$v(rate)))/((10000000.0/$v(rate))*$v(rate)/$v(pps)))} 3528 } 3529 TIMIT - 3530 MIX { 3531 expr {(($t - $v(startsmp)) / (double($v(rate))/$v(pps)))} 3532 } 3533 WAVES { 3534 expr {(($t - (double($v(startsmp))/$v(rate)) )*$v(pps))} 3535 } 3536 } 3537} 3538 3539proc Time2DTime {t} { 3540 global v 3541 3542 switch $v(labfmt) { 3543 HTK { 3544 expr {($t/10000000.0)} 3545 } 3546 WAVES { 3547 expr {$t} 3548 } 3549 TIMIT - 3550 MIX - 3551 default { 3552 expr {double($t)/$v(rate)} 3553 } 3554 } 3555} 3556 3557proc DTime2Time {t} { 3558 global v 3559 3560 switch $v(labfmt) { 3561 HTK { 3562 expr {int($t*10000000.0)} 3563 } 3564 WAVES { 3565 expr {$t} 3566 } 3567 TIMIT - 3568 MIX - 3569 default { 3570 expr {int($t*$v(rate))} 3571 } 3572 } 3573} 3574 3575proc Coord2Time {x} { 3576 global v 3577 3578 switch $v(labfmt) { 3579 HTK { 3580 expr {int(($x*$v(rate)/$v(pps)+$v(startsmp))*(10000000.0/$v(rate)))} 3581 } 3582 WAVES { 3583 expr {double($x)/$v(pps)+double($v(startsmp))/$v(rate)} 3584 } 3585 TIMIT - 3586 MIX - 3587 default { 3588 expr {int($v(startsmp)+$x*(double($v(rate))/$v(pps)))} 3589 } 3590 } 3591} 3592 3593proc Coord2Sample {x} { 3594 global v 3595 3596 expr {int($v(startsmp)+$x*double($v(rate))/$v(pps))} 3597} 3598 3599proc BoundaryEnter {x} { 3600 global c _mb 3601 3602 set _mb 1 3603 $c itemconfig current -fill red 3604 $c configure -cursor sb_h_double_arrow 3605} 3606 3607proc BoundaryLeave {x} { 3608 global c v 3609 3610 $c itemconfig current -fill $v(fg) 3611 $c configure -cursor {} 3612} 3613 3614proc MarkerEnter {x} { 3615 global c 3616 3617 $c itemconfig current -fill red 3618 $c configure -cursor sb_h_double_arrow 3619} 3620 3621proc MarkerLeave {x} { 3622 global c v 3623 3624 $c itemconfig current -fill $v(fg) 3625 $c configure -cursor {} 3626} 3627 3628proc PutMarker {m x y f} { 3629 global c v _mx _mb 3630 3631 if {$_mx == 0} return 3632 if {$y > [expr $v(waveh) + $v(spegh) + $v(timeh)]} { 3633 if {$_mb == 1 && $f == 1} { 3634 MoveBoundary $x 3635 } 3636 return 3637 } 3638 if {$f == 1} { 3639 if {$x < 0 && [lindex [$c xview] 0] > 0} { 3640 $c xview scroll -1 unit 3641 update 3642 SendXScroll 3643 } 3644 if {$x >= [winfo width $c]} { 3645 $c xview scroll 1 unit 3646 update 3647 SendXScroll 3648 } 3649 3650 set xc [$c canvasx $x] 3651 3652 if {$xc < 0} { set xc 0 } 3653 if {$xc > $v(width)} { set xc $v(width) } 3654 3655 set t [Coord2Time $xc] 3656 } else { 3657 set xc [Time2Coord $x] 3658 set t $x 3659 } 3660 if {$t >= [snd length]} { 3661 set t [expr {[snd length]-1}] 3662 } 3663 $c itemconf $m -tags [list mark $t $m] 3664 $c coords $m $xc 0 $xc $v(toth) 3665 3666 if {$m == "m1"} { 3667 set tm2 [Marker2Time m2] 3668 if {$t > $tm2} { 3669 $c itemconf m2 -tags [list mark $tm2 m3] 3670 $c itemconf m1 -tags [list mark $t m2] 3671 $c itemconf m3 -tags [list mark [Marker2Time m3] m1] 3672 } 3673 } else { 3674 set tm1 [Marker2Time m1] 3675 if {$t < $tm1} { 3676 $c itemconf m1 -tags [list mark $tm1 m3] 3677 $c itemconf m2 -tags [list mark $t m1] 3678 $c itemconf m3 -tags [list mark [Marker2Time m3] m2] 3679 } 3680 } 3681 3682 if {$v(fillmark)} { 3683 $c coords mfill [Time2Coord [Marker2Time m1]] 0 \ 3684 [Time2Coord [Marker2Time m2]] $v(toth) 3685 } 3686 3687 set ox1 [expr $v(scrh) + [Time2DTime [Marker2Time m1]] * $v(opps) / 1000.0] 3688 set ox2 [expr $v(scrh) + [Time2DTime [Marker2Time m2]] * $v(opps) / 1000.0] 3689 .of.c coords mark $ox1 2 $ox2 30 3690 3691 if {$f == 1} { 3692 DrawZoom 1 3693 DrawSect 3694 set t1 [Marker2Time m1] 3695 set t2 [Marker2Time m2] 3696 set l [expr $t2 - $t1] 3697 set tt1 [Time2DTime $t1] 3698 set tt2 [Time2DTime $t2] 3699 set ll [expr $tt2 - $tt1] 3700 SetMsg [format "From: %9s to: %9s length: %9s\t(%.3f - %.3f, %.3f)"\ 3701 $t1 $t2 $l $tt1 $tt2 $ll] mark 3702 set v(fromto) [list $t1 $t2 $l $tt1 $tt2 $ll] 3703 } 3704 3705 foreach p $v(plugins) { 3706 namespace inscope $p Putmark $m 3707 } 3708 update 3709} 3710 3711proc SendPutMarker {m x} { 3712 global c v 3713 3714 set xc [$c canvasx $x] 3715 if {$v(mlink) == 1} { 3716 foreach prg [winfo interps] { 3717 if [regexp .*xs.* $prg] { 3718 if {[winfo name .] != $prg} { 3719 set t [Coord2Time $xc] 3720 send $prg PutMarker $m $t 0 0 3721 } 3722 } 3723 } 3724 } 3725} 3726 3727proc Marker2Sample {m} { 3728 global c 3729 3730 Time2Sample [lindex [$c gettags $m] 1] 3731} 3732 3733proc Marker2Time {m} { 3734 global c 3735 3736 lindex [$c gettags $m] 1 3737} 3738 3739proc DrawCrossHairs {} { 3740 global c v 3741 3742 if {$v(ch)} { 3743 $c delete ch1 ch2 3744 if {$::tcl_platform(platform) == "windows"} { 3745# $c create line 0 0 0 0 -width 2 -stipple gray50 -tags [list ch1]\ 3746# -fill $v(gridcolor) 3747# $c create line 0 0 0 0 -width 2 -stipple gray50 -tags [list ch2]\ 3748# -fill $v(gridcolor) 3749 $c create line 0 0 0 0 -width 1 -tags [list ch1]\ 3750 -fill $v(gridcolor) 3751 $c create line 0 0 0 0 -width 1 -tags [list ch2]\ 3752 -fill $v(gridcolor) 3753 } else { 3754 $c create line 0 0 0 0 -width 1 -stipple gray50 -tags [list ch1]\ 3755 -fill $v(gridcolor) 3756 $c create line 0 0 0 0 -width 1 -stipple gray50 -tags [list ch2]\ 3757 -fill $v(gridcolor) 3758 } 3759 $c lower ch1 m1 3760 $c lower ch2 m1 3761 } else { 3762 $c delete ch1 ch2 3763 } 3764} 3765 3766proc PutCrossHairs {x y} { 3767 global c v 3768 3769 set xc [$c canvasx $x] 3770 set yc [$c canvasy $y] 3771 set f 0.0 3772 catch { set f [expr $v(topfr) * ($v(spegh) - ($yc - $v(waveh))) / $v(spegh)]} 3773 if {$f < 0.0} { set f 0.0 } 3774 if {$f > 0.5*$v(rate)} { set f [expr 0.5*$v(rate)] } 3775 3776 if {$v(ch)} { 3777 $c coords ch1 $xc 0 $xc $v(toth) 3778 $c coords ch2 0 $yc $v(width) $yc 3779 set s [Coord2Time $xc] 3780 set t [expr double($xc) / $v(pps)] 3781 3782 SetMsg "time: $t\tsample: $s\tfrequency: $f" 3783 } else { 3784 $c coords ch1 -1 -1 -1 -1 3785 $c coords ch2 -1 -1 -1 -1 3786 } 3787 if [winfo exists .sect] { DrawSectMarks f $f } 3788} 3789 3790proc OpenSectWindow {} { 3791 global s v 3792 3793 catch {destroy .sect} 3794 toplevel .sect -width $s(sectwinw) -height $s(sectwinh) 3795 wm title .sect "Spectrum section plot" 3796 wm geometry .sect +$s(sectwinx)+$s(sectwiny) 3797 pack propagate .sect 0 3798 3799 set s(ostart) "" 3800 3801 pack [frame .sect.f] -side bottom -fill x 3802 label .sect.f.lab -width 1 -relief sunken -bd 1 -anchor w 3803 pack .sect.f.lab -side left -expand yes -fill x 3804 pack [button .sect.f.exitB -text Close -command {destroy .sect}] -side left 3805 pack [canvas .sect.c -closeenough 5 -cursor draft_small -bg $v(bg)] -fill both -expand true 3806 3807 pack [frame .sect.f1] 3808 label .sect.f1.l1 -text "FFT points:" -anchor w 3809# pack [entry .sect.f2.e1 -textvar s(fftlen) -wi 6] -side left 3810 tk_optionMenu .sect.f1.m1 s(fftlen) 64 128 256 512 1024 2048 4096 8192 16384 3811 for {set n 0} {$n < 7} {incr n} { 3812 .sect.f1.m1.menu entryconfigure $n -command DrawSect 3813 } 3814 label .sect.f1.l2 -text "Window:" 3815 tk_optionMenu .sect.f1.m2 s(wintype) \ 3816 Hamming Hanning Bartlett Blackman Rectangle 3817 pack .sect.f1.l1 .sect.f1.m1 .sect.f1.l2 .sect.f1.m2 -side left 3818# pack [label .sect.f2.l2 -text "Preemphasis:" -anchor w] -side left 3819# pack [entry .sect.f2.e2 -textvar s(ref) -wi 6] -side left 3820 3821 pack [frame .sect.f2] 3822 label .sect.f2.l1 -text "Analysis:" 3823 tk_optionMenu .sect.f2.m1 s(atype) FFT LPC 3824 .sect.f2.m1.menu entryconfigure 0 -command [list LPCcontrols disabled] 3825 .sect.f2.m1.menu entryconfigure 1 -command [list LPCcontrols normal] 3826 label .sect.f2.l2 -text "Order:" 3827 entry .sect.f2.e -textvariable s(lpcorder) -width 3 3828 scale .sect.f2.s -variable s(lpcorder) -from 1 -to 40 -orient horiz \ 3829 -length 80 -show no 3830 bind .sect.f2.s <Button1-Motion> DrawSect 3831 pack .sect.f2.l1 .sect.f2.m1 .sect.f2.l2 .sect.f2.e .sect.f2.s -side left 3832 if {$s(atype) != "LPC"} { LPCcontrols disabled } 3833 if {$s(lpcorder) < 1} { set s(lpcorder) 20 } 3834 3835 pack [frame .sect.f3] 3836 pack [label .sect.f3.l2 -text "Reference:" -anchor w] -side left 3837 pack [entry .sect.f3.e2 -textvar s(ref) -wi 6] -side left 3838 pack [label .sect.f3.u1 -text "dB" -anchor w] -side left 3839 pack [label .sect.f3.l3 -text "Range:" -anchor w] -side left 3840 pack [entry .sect.f3.e3 -textvar s(range) -wi 5] -side left 3841 pack [label .sect.f3.u2 -text "dBfs" -anchor w] -side left 3842 3843# label $w.r.f11.l -text "Analysis bandwidth (Hz):" -width 25 -anchor w 3844# entry $w.r.f11.e -textvar s(anabw) -wi 6 3845# pack $w.r.f11.l $w.r.f11.e -side left 3846 3847 pack [frame .sect.f4] 3848 pack [button .sect.f4.lockB -text Lock -command {set s(ostart) $s(start);set s(oend) $s(end)}] -side left 3849 pack [button .sect.f4.printB -text Print... -command {Print .sect.c $s(sectwinh)}] -side left 3850 pack [button .sect.f4.exportB -text Export... -command Export] -side left 3851 3852 update idletasks 3853 DrawSect 3854 3855 bind .sect <Configure> DrawSect 3856 bind .sect <Any-Key> DrawSect 3857 bind .sect.c <ButtonPress-1> { set s(rx) %x; set s(ry) %y ;.sect.c coords relmark 0 0 0 0;.sect.c coords df -10 -10;.sect.c coords db -10 -10} 3858 bind .sect.c <ButtonRelease-1> { set s(rx) -1 } 3859 bind .sect.c <Motion> {DrawSectMarks %x %y} 3860 bind .sect.c <Leave> {.sect.c coords sx -1 -1 -1 -1;.sect.c coords sy -1 -1 -1 -1} 3861} 3862 3863proc LPCcontrols {state} { 3864 .sect.f2.e configure -state $state 3865 .sect.f2.s configure -state $state 3866} 3867 3868proc DrawSect {} { 3869 global c s v 3870 3871 if [winfo exists .sect] { 3872 set geom [lindex [split [wm geometry .sect] +] 0] 3873 set s(sectwinw) [lindex [split $geom x] 0] 3874 set s(sectwinh) [lindex [split $geom x] 1] 3875 set s(sectwinx) [lindex [split [wm geometry .sect] +] 1] 3876 set s(sectwiny) [lindex [split [wm geometry .sect] +] 2] 3877 set s(sectw) [expr [winfo width .sect.c] - 25] 3878 set s(secth) [expr [winfo height .sect.c] - 20] 3879 set s(sectcw) [winfo width .sect.c] 3880 set s(sectch) [winfo height .sect.c] 3881 3882 set s(start) [Marker2Sample m1] 3883 set s(end) [Marker2Sample m2] 3884 if {$s(start) == $s(end)} { set s(start) [expr $s(end) - 1]} 3885 .sect.c delete sect 3886 set s(top) [expr int(($s(ref) + $s(range)) / 10.0)] 3887 set s(bot) [expr int($s(ref) / 10.0 )] 3888 3889catch { 3890 if {$s(ostart) != ""} { 3891 .sect.c create section 25 0 -sound snd -height $s(secth)\ 3892 -width $s(sectw) -maxvalue [expr 10.0*$s(top)] \ 3893 -minvalue [expr 10.0*$s(bot)] \ 3894 -start $s(ostart) -end $s(oend) -tags sect \ 3895 -fftlen $s(fftlen) -analysistype $s(atype) \ 3896 -lpcorder $s(lpcorder) \ 3897 -winlen $s(fftlen) -channel $v(vchan) -fill red \ 3898 -topfr $v(topfr) -windowtype $s(wintype) 3899 } 3900 .sect.c create section 25 0 -sound snd -height $s(secth) \ 3901 -width $s(sectw) -maxvalue [expr 10.0*$s(top)] \ 3902 -minval [expr 10.0*$s(bot)] \ 3903 -start $s(start) -end $s(end) -tags sect -fftlen $s(fftlen) \ 3904 -winlen $s(fftlen) -channel $v(vchan) -frame 1 \ 3905 -debug $::debug -fill $v(fg) -analysistype $s(atype) \ 3906 -lpcorder $s(lpcorder) -topfr $v(topfr) -windowtype $s(wintype) 3907 } 3908 .sect.c create text -10 -10 -text df: -font $v(sfont) -tags df \ 3909 -fill blue 3910 .sect.c create text -10 -10 -text "0 db" -font $v(sfont) -tags db \ 3911 -fill red 3912 set pps [expr int(double($s(sectw))/($v(topfr)/1000.0) + .5)] 3913 snack::timeAxis .sect.c 25 $s(secth) $s(sectw) 20 $pps \ 3914 -tags sect -fill $v(fg) -font $v(sfont) 3915 3916 for {set i $s(top)} {$i > $s(bot)} {incr i -1} { 3917 set lab [expr 10 * $i] 3918 .sect.c create text 0 \ 3919 [expr ($i - $s(top)) * $s(secth) / ($s(bot) - $s(top))] \ 3920 -text $lab \ 3921 -tags sect -font $v(sfont) -anchor w -fill $v(fg) 3922 } 3923 3924 .sect.c create text 2 2 -text dB -font $v(sfont) -tags sect -anchor nw\ 3925 -fill $v(fg) 3926 .sect.c create text $s(sectw) $s(secth) -text kHz -font $v(sfont)\ 3927 -tags sect -anchor nw -fill $v(fg) 3928 } 3929} 3930 3931proc Export {} { 3932 global s v f 3933 3934 set s(start) [Marker2Sample m1] 3935 set s(end) [Marker2Sample m2] 3936 3937 if {$s(start) == $s(end)} { set s(start) [expr $s(end) - 1]} 3938 3939 set ps [snd dBPowerSpectrum -start $s(start) -end $s(end) \ 3940 -fftlen $s(fftlen) -windowlen $s(fftlen) -channel $v(vchan) \ 3941 -windowtype $s(wintype) -analysistype $s(atype) \ 3942 -lpcorder $s(lpcorder)] 3943 3944 set file [tk_getSaveFile -title "Export spectral data" -initialfile spectrum.txt] 3945 if {$file == ""} return 3946 if {[catch {open $file w} out]} { 3947 return $out 3948 } else { 3949 set df [expr {([snd cget -rate] / 2.0) / $s(fftlen)}] 3950 set freq [expr {$df / 2.0}] 3951 puts $out "File: $f(sndfile) $s(start)-$s(end)" 3952 puts $out "$s(wintype) window, $s(fftlen) points" 3953 puts $out "Frequency (Hz) Level (dB)" 3954 foreach e $ps { 3955 puts $out [format "%f\t%f" $freq $e] 3956 set freq [expr {$freq + $df}] 3957 } 3958 close $out 3959 } 3960} 3961 3962proc DrawSectMarks {x y} { 3963 global s v 3964 3965 if {[.sect.c find withtag sm] == ""} { 3966 if {$::tcl_platform(platform) == "windows"} { 3967# .sect.c create line 0 0 0 $s(sectch) -width 2 -stipple gray50 -tags [list sx sm] -fill $v(fg) 3968# .sect.c create line 0 0 $s(sectcw) 0 -width 2 -stipple gray50 -tags [list sy sm] -fill $v(fg) 3969# .sect.c create line 0 0 0 0 -width 2 -stipple gray50 -tags [list relmark] -fill $v(fg) 3970 .sect.c create line 0 0 0 $s(sectch) -width 1 -tags [list sx sm] -fill $v(fg) 3971 .sect.c create line 0 0 $s(sectcw) 0 -width 1 -tags [list sy sm] -fill $v(fg) 3972 .sect.c create line 0 0 0 0 -width 1 -tags [list relmark] -fill $v(fg) 3973 } else { 3974 .sect.c create line 0 0 0 $s(sectch) -width 1 -stipple gray50 -tags [list sx sm] -fill $v(fg) 3975 .sect.c create line 0 0 $s(sectcw) 0 -width 1 -stipple gray50 -tags [list sy sm] -fill $v(fg) 3976 .sect.c create line 0 0 0 0 -width 1 -stipple gray50 -tags [list relmark relmarkux] -arrow both -fill $v(fg) 3977 } 3978 } 3979 3980 if {$x != "f"} { 3981 set xc [.sect.c canvasx $x] 3982 set yc [.sect.c canvasx $y] 3983 } else { 3984 set xc [expr 25+int($s(sectw) * $y / $v(topfr))] 3985 set yc [lindex [.sect.c coords sy] 1] 3986 } 3987 .sect.c coords sx $xc 0 $xc $s(sectch) 3988 .sect.c coords sy 0 $yc $s(sectcw) $yc 3989 set f [expr int(double($v(topfr)) * ($xc - 25) / $s(sectw) + .5)] 3990 if {$f < 0} { set f 0 } 3991 set db [format "%.1f" [expr 10.0 * ($s(bot) - $s(top)) * double($yc) / $s(secth) + 10.0 * $s(top)]] 3992 3993 if {$s(rx) != -1} { 3994 set rx [.sect.c canvasx $s(rx)] 3995 set ry [.sect.c canvasy $s(ry)] 3996 .sect.c coords relmark $rx $ry $xc $yc 3997 .sect.c coords df [expr $rx + ($xc-$rx)/2] $ry 3998 .sect.c coords db $rx [expr $ry + ($yc-$ry)/2] 3999 4000 set df [expr abs(int($v(topfr) * ($rx - $xc)/ $s(sectw)))] 4001 .sect.c itemconf df -text "df: $df" 4002 set ddb [format "%.1f" [expr $s(range) * ($ry - $yc) / $s(secth)]] 4003 .sect.c itemconf db -text "db: $ddb" 4004 } else { 4005# .sect.c coords relmark 0 0 0 0 4006# .sect.c coords df -10 -10 4007# .sect.c coords db -10 -10 4008 } 4009 4010 .sect.f.lab config -text "Frequency: $f Hz, amplitude: $db dB" 4011} 4012 4013proc OpenZoomWindow {} { 4014 global z v 4015 4016 catch {destroy .zoom} 4017 catch {destroy .zmenu} 4018 toplevel .zoom -width $z(zoomwinw) -height $z(zoomwinh) 4019 wm title .zoom "Zoom view" 4020 wm geometry .zoom +$z(zoomwinx)+$z(zoomwiny) 4021 pack propagate .zoom 0 4022 4023 frame .zoom.f 4024 label .zoom.f.lab -text "Press right mouse button for menu" -width 1 -relief sunken -bd 1 -anchor w 4025 pack .zoom.f.lab -side left -expand yes -fill x 4026 pack [button .zoom.f.xzoomB -text X-zoom -command {DrawZoom 1}] -side left 4027 pack [button .zoom.f.yizoomB -text "Y-zoom in" -command {DrawZoom 2}] -side left 4028 pack [button .zoom.f.yozoomB -text "Y-zoom out" -command {DrawZoom .5}] -side left 4029 pack [button .zoom.f.exitB -text Close -command {destroy .zoom}] -side left 4030 pack .zoom.f -side bottom -fill x 4031 pack [canvas .zoom.c -closeenough 5 -bg $v(bg)] -fill both -expand true 4032 4033 update idletasks 4034 DrawZoom 1 4035 4036 menu .zmenu -tearoff false 4037 .zmenu add command -label "Play Range" -command PlayMark 4038 .zmenu add command -label "Mark Start" -command {PutZMarker zm1 $x} 4039 .zmenu add command -label "Mark End" -command {PutZMarker zm2 $x} 4040 if {[string match macintosh $::tcl_platform(platform)] || \ 4041 [string match Darwin $::tcl_platform(os)]} { 4042 bind $c <Control-1> \ 4043 {set x %x; set y %y; catch {tk_popup .zmenu %X %Y 0}} 4044 } else { 4045 bind .zoom.c <3> {set x %x; set y %y; catch {tk_popup .zmenu %X %Y 0}} 4046 } 4047 bind .zoom <Configure> { DrawZoom 1 } 4048} 4049 4050proc DrawZoom {factor} { 4051 global z v f 4052 4053 if [winfo exists .zoom] { 4054 set geom [lindex [split [wm geometry .zoom] +] 0] 4055 set z(zoomwinw) [lindex [split $geom x] 0] 4056 set z(zoomwinh) [lindex [split $geom x] 1] 4057 set z(zoomwinx) [lindex [split [wm geometry .zoom] +] 1] 4058 set z(zoomwiny) [lindex [split [wm geometry .zoom] +] 2] 4059 set z(zoomwavw) [winfo width .zoom.c] 4060 set z(zoomwavh) [winfo height .zoom.c] 4061 set z(f) [expr $z(f) * $factor] 4062 4063 set start [Marker2Sample m1] 4064 set end [Marker2Sample m2] 4065 4066 if {$start == $end} { set end [expr $start + 1]} 4067 set zoompps [expr double($z(zoomwavw)) * $v(rate) / ($end - $start)] 4068 4069 .zoom.c delete zoomwave zm1 zm2 4070 if {$v(linkfile) && $f(sndfile) != ""} { 4071 .zoom.c create waveform 0 [expr $z(zoomwavh)/2] -sound snd \ 4072 -height [expr int($z(zoomwavh) * $z(f))] \ 4073 -start $start -end $end -channel $v(vchan) \ 4074 -pixels $zoompps -tags zoomwave -anchor w -fill $v(fg) \ 4075 -shapefile [file rootname [file tail $f(spath)$f(sndfile)]].shape 4076 } else { 4077 .zoom.c create waveform 0 [expr $z(zoomwavh)/2] -sound snd \ 4078 -height [expr int($z(zoomwavh) * $z(f))] \ 4079 -start $start -end $end -channel $v(vchan) \ 4080 -pixels $zoompps -tags zoomwave -anchor w -fill $v(fg) 4081 } 4082 .zoom.c create line 1 0 1 $z(zoomwavh) -width 1 -tags zm1 -fill $v(fg) 4083 .zoom.c create line [expr $z(zoomwavw) - 1] 0 [expr $z(zoomwavw) - 1] $z(zoomwavh) -width 1 -tags zm2 -fill $v(fg) 4084 .zoom.c bind zm1 <B1-Motion> { PutZMarker zm1 %x } 4085 .zoom.c bind zm2 <B1-Motion> { PutZMarker zm2 %x } 4086 .zoom.c bind zm1 <ButtonPress-1> { set _mx 0 } 4087 .zoom.c bind zm2 <ButtonPress-1> { set _mx 0 } 4088 .zoom.c bind zm1 <ButtonRelease-1> { set _mx 0 } 4089 .zoom.c bind zm2 <ButtonRelease-1> { set _mx 0 } 4090 bind .zoom.c <ButtonPress-1> { PutZMarker zm1 %x; set _mx 1 } 4091 bind .zoom.c <ButtonRelease-1> { PutZMarker zm2 %x; set _mx 1} 4092 set z(zoomt1) [Marker2Time m1] 4093 set z(zoomt2) [Marker2Time m2] 4094 } 4095} 4096 4097proc PutZMarker {m x} { 4098 global z _mx 4099 4100 if {$_mx == 0} return 4101 4102 set xc [.zoom.c canvasx $x] 4103 if {$xc < 0} { set xc 0 } 4104 if {$xc > $z(zoomwavw)} { set xc $z(zoomwavw) } 4105 .zoom.c coords $m $xc 0 $xc $z(zoomwavh) 4106 4107 set t [TimeRound [expr $z(zoomt1) + ($z(zoomt2) - $z(zoomt1)) * double($xc) / $z(zoomwavw)]] 4108 set n [Time2Sample $t] 4109 set s [snd sample $n] 4110 if {$m == "zm1"} { 4111 .zoom.f.lab config -text "Marker 1 at $n ($s)" 4112 PutMarker m1 $n 0 0 4113 } else { 4114 .zoom.f.lab config -text "Marker 2 at $n ($s)" 4115 PutMarker m2 $n 0 0 4116 } 4117} 4118 4119proc WS {} { 4120 catch {destroy .ws} 4121 toplevel .ws 4122 wm title .ws "WaveSurfer window" 4123 4124 lappend ::auto_path /afs/tmh.kth.se/tmh/home/speech/kare/wavesurfer/src 4125 4126 package require -exact wsurf 1.0 4127 4128 set w [wsurf .ws.ws -collapser 0 -title ""] 4129 pack $w -expand 0 -fill both 4130 $w configure -sound snd 4131 $w configure -configuration ../wavesurfer/src/configurations/Spectrogram.conf 4132 update idletasks 4133 $w xzoom 0.4 0.6 4134 $w xscroll moveto 0.4 4135} 4136 4137proc Version {} { 4138 global c v 4139 4140 SetMsg "xs version $v(p_version), settings for $v(s_version)" 4141 catch {::http::geturl http://www.speech.kth.se/snack/xs.html\ 4142 -command VersionMore} 4143 set c .cf.fc.c 4144} 4145 4146proc VersionMore {token} { 4147 global v 4148 4149 set data [::http::data $token] 4150 regexp {version is ([0-9].[0-9])} $data junk version 4151 SetMsg "xs version $v(p_version), settings for $v(s_version), current download version is $version" 4152} 4153 4154# 4155# Miscellaneous subroutines 4156# 4157 4158proc Help {url} { 4159 global v lab_path 4160 4161 if {$::tcl_platform(platform) == "windows"} { 4162 if {[string match $::tcl_platform(os) "Windows NT"]} { 4163 exec $::env(COMSPEC) /c start $url & 4164 } { 4165 exec start $url & 4166 } 4167 } else { 4168 if [catch {exec sh -c "netscape -remote 'openURL($url)' -raise"} res] { 4169 if [string match *netscape* $res] { 4170 exec sh -c "netscape $url" & 4171 } 4172 } 4173 } 4174} 4175 4176proc NewWin {} { 4177 global f 4178 4179 if {$::tcl_platform(platform) == "windows"} { 4180 exec [info nameofexecutable] $f(prog) & 4181 } else { 4182 exec $f(prog) -geometry [xsGetGeometry] & 4183 } 4184} 4185 4186proc Reset {} { 4187 global v f s v_copy f_copy s_copy 4188 4189 array set v $v_copy 4190 array set f $f_copy 4191 array set s $s_copy 4192} 4193 4194proc Settings {} { 4195 global v c f s v_copy f_copy s_copy 4196 4197 StopPlay 4198 set w .dim 4199 catch {destroy $w} 4200 toplevel $w 4201 wm title $w {Settings} 4202 4203 set start [Coord2Sample [$c canvasx [expr [winfo width .cf.fc]/2 - 100]]] 4204 set end [Coord2Sample [$c canvasx [expr [winfo width .cf.fc]/2 + 100]]] 4205 4206 set v_copy [array get v] 4207 set f_copy [array get f] 4208 set s_copy [array get s] 4209 4210 pack [frame $w.ll] -side left -anchor e 4211 pack [canvas $w.ll.c -height [expr $v(waveh)+$v(spegh)] -width 200 \ 4212 -highlightthickness 0] 4213 4214 pack [frame $w.l] -side left -anchor n -fill y 4215 pack [label $w.l.l1 -text Appearance:] 4216 4217 pack [frame $w.l.f3] 4218 pack [label $w.l.f3.l -text "Time scale (pixels/second):" -width 25 -anchor w] -side left 4219 pack [entry $w.l.f3.e -textvar v(pps) -wi 6] -side left 4220 pack [scale $w.l.f3.s -variable v(pps) -orient horiz -from 1 -to 1000 -command "$w.ll.c itemconf both -width 200 -start $start -pixels " -showvalue no] -side left 4221 4222 pack [frame $w.l.f1] 4223 pack [label $w.l.f1.l -text "Waveform height:" -width 25 -anchor w] -side left 4224 pack [entry $w.l.f1.e -textvar v(waveh) -wi 6] -side left 4225 pack [scale $w.l.f1.s -variable v(waveh) -orient horiz -from 0 -to 1000 -showvalue no -command {.dim.ll.c configure -height [expr $v(waveh) + $v(spegh)];.dim.ll.c coords speg 0 $v(waveh);.dim.ll.c itemconf wave -height }] -side left 4226 4227 pack [frame $w.l.f2] 4228 pack [label $w.l.f2.l -text "Spectrogram height:" -width 25 -anchor w] -side left 4229 pack [entry $w.l.f2.e -textvar v(spegh) -wi 6] -side left 4230 pack [scale $w.l.f2.s -variable v(spegh) -orient horiz -from 0 -to 1000 -command {.dim.ll.c configure -height [expr $v(waveh) + $v(spegh)];.dim.ll.c itemconf speg -height } -showvalue no] -side left 4231 4232 pack [frame $w.l.f20] 4233 pack [label $w.l.f20.l -text "Cut spectrogram at freq:" -width 25 -anchor w] -side left 4234 pack [entry $w.l.f20.e -textvar v(topfr) -wi 6] -side left 4235 pack [scale $w.l.f20.s -variable v(topfr) -orient horiz -from 0 -to [expr $v(rate)/2] -command "DrawSect;$w.ll.c itemconf speg -topfreq " -showvalue no] -side left 4236 4237 pack [frame $w.l.f30] 4238 pack [label $w.l.f30.l -text "Brightness" -width 25 -anchor w] -side left 4239 pack [entry $w.l.f30.e -textvar v(brightness) -wi 6] -side left 4240 pack [scale $w.l.f30.b -variable v(brightness) -showvalue no \ 4241 -orient horiz -command "$w.ll.c itemconf speg -brightness " \ 4242 -from -100 -to 100 -res 0.1] 4243 4244 pack [frame $w.l.f31] 4245 pack [label $w.l.f31.l -text "Contrast" -width 25 -anchor w] -side left 4246 pack [entry $w.l.f31.e -textvar v(contrast) -wi 6] -side left 4247 pack [scale $w.l.f31.c -variable v(contrast) -showvalue no\ 4248 -orient horiz -command "$w.ll.c itemconf speg -contrast" \ 4249 -from -100 -to 100 -res 0.1] 4250 4251# pack [frame $w.l.f21] 4252# label $w.l.f21.l -text "Scroll area width:" -width 25 -anchor w 4253# entry $w.l.f21.e -textvar v(scrw) -wi 6 4254# pack $w.l.f21.l $w.l.f21.e -side left 4255 4256 pack [frame $w.l.f41] 4257 label $w.l.f41.l -text "Foreground color:" -width 25 -anchor w 4258 entry $w.l.f41.e -textvar v(fg) -wi 6 4259 pack $w.l.f41.l $w.l.f41.e -side left 4260 bind $w.l.f41.e <Key-Return> {.dim.ll.c itemconf wave -fill $v(fg)} 4261 4262 pack [frame $w.l.f41b] 4263 label $w.l.f41b.l -text "Background color:" -width 25 -anchor w 4264 entry $w.l.f41b.e -textvar v(bg) -wi 6 4265 pack $w.l.f41b.l $w.l.f41b.e -side left 4266 bind $w.l.f41b.e <Key-Return> {$c config -bg $v(bg); .cf.fyc.yc config -bg $v(bg); catch {.zoom.c config -bg $v(bg)}; catch {.sect.c config -bg $v(bg)}} 4267 4268 pack [frame $w.l.f42] 4269 label $w.l.f42.l -text "Grid frequency spacing (Hz):" -width 25 -anchor w 4270 entry $w.l.f42.e -textvar v(gridfspacing) -wi 6 4271 pack $w.l.f42.l $w.l.f42.e -side left 4272 bind $w.l.f42.e <Key-Return> {.dim.ll.c itemconf speg -gridf $v(gridfspacing)} 4273 4274 pack [frame $w.l.f43] 4275 label $w.l.f43.l -text "Grid time spacing: (s)" -width 25 -anchor w 4276 entry $w.l.f43.e -textvar v(gridtspacing) -wi 6 4277 pack $w.l.f43.l $w.l.f43.e -side left 4278 bind $w.l.f43.e <Key-Return> {.dim.ll.c itemconf speg -gridt $v(gridtspacing)} 4279 4280 pack [frame $w.l.f44] 4281 label $w.l.f44.l -text "Grid color:" -width 25 -anchor w 4282 entry $w.l.f44.e -textvar v(gridcolor) -wi 6 4283 pack $w.l.f44.l $w.l.f44.e -side left 4284 bind $w.l.f44.e <Key-Return> {DrawCrossHairs;.dim.ll.c itemconf speg -gridc $v(gridcolor)} 4285 4286 pack [frame $w.l.f45] 4287 label $w.l.f45.l -text "Spectrogram color:" -width 25 -anchor w 4288 tk_optionMenu $w.l.f45.cm v(cmap) grey color1 color2 4289 $w.l.f45.cm.menu entryconfigure 0 -command {.dim.ll.c itemconf speg -col $v($v(cmap))} 4290 $w.l.f45.cm.menu entryconfigure 1 -command {.dim.ll.c itemconf speg -col $v($v(cmap))} 4291 $w.l.f45.cm.menu entryconfigure 2 -command {.dim.ll.c itemconf speg -col $v($v(cmap))} 4292 pack $w.l.f45.l $w.l.f45.cm -side left 4293 4294 pack [frame $w.r] -side left -anchor n -fill y -expand true 4295 4296 pack [label $w.r.l2 -text "Spectrogram analysis:"] 4297 4298 pack [frame $w.r.f1] 4299 label $w.r.f1.l -text "FFT window length (points):" -width 25 -anchor w 4300 entry $w.r.f1.e -textvar v(fftlen) -wi 6 4301 pack $w.r.f1.l $w.r.f1.e -side left 4302 bind $w.r.f1.e <Key-Return> {.dim.ll.c itemconf speg -fftlen $v(fftlen)} 4303 4304 pack [frame $w.r.f2] 4305 label $w.r.f2.l -text "Analysis bandwidth (Hz):" -width 25 -anchor w 4306 entry $w.r.f2.e -textvar v(anabw) -wi 6 4307 pack $w.r.f2.l $w.r.f2.e -side left 4308 bind $w.r.f2.e <Key-Return> {.dim.ll.c itemconf speg -winlen [expr int($v(rate) / $v(anabw))]} 4309 4310 pack [frame $w.r.f3] 4311 label $w.r.f3.l -text "Pre-emphasis factor:" -width 25 -anchor w 4312 entry $w.r.f3.e -textvar v(preemph) -wi 6 4313 pack $w.r.f3.l $w.r.f3.e -side left 4314 bind $w.r.f3.e <Key-Return> {.dim.ll.c itemconf speg -preem $v(preemph)} 4315 4316# pack [label $w.r.l3 -text "Spectrum section analysis:"] -pady 10 4317 4318# pack [frame $w.r.f10] 4319# label $w.r.f10.l -text "FFT window length (points):" -width 25 -anchor w 4320# entry $w.r.f10.e -textvar s(fftlen) -wi 6 4321# pack $w.r.f10.l $w.r.f10.e -side left 4322 4323# pack [frame $w.r.f11] 4324# label $w.r.f11.l -text "Analysis bandwidth (Hz):" -width 25 -anchor w 4325# entry $w.r.f11.e -textvar s(anabw) -wi 6 4326# pack $w.r.f11.l $w.r.f11.e -side left 4327 4328## pack [button $w.r.sectB -text Apply -command DrawSect] -pady 5 4329# bind $w.r.f10.e <Key-Return> DrawSect 4330# bind $w.r.f11.e <Key-Return> DrawSect 4331 4332# pack [frame $w.r.f5] 4333# label $w.r.f5.l -text "Label font:" -width 11 -anchor w 4334# entry $w.r.f5.e -textvar v(font) -wi 20 4335# pack $w.r.f5.l $w.r.f5.e -side left 4336 4337# pack [frame $w.r.f6] 4338# label $w.r.f6.l -text "Axes font:" -width 11 -anchor w 4339# entry $w.r.f6.e -textvar v(sfont) -wi 20 4340# pack $w.r.f6.l $w.r.f6.e -side left 4341# bind $w.r.f6.e <Key-Return> DrawSect 4342 4343# pack [label $w.r.l4 -text "Raw/unknown file input:"] -pady 10 4344# pack [frame $w.r.f12] 4345# label $w.r.f12.l -text "Unknown file header size:" -width 25 -anchor w 4346# entry $w.r.f12.e -textvar f(skip) -wi 6 4347# pack $w.r.f12.l $w.r.f12.e -side left 4348 4349# pack [frame $w.r.f9] 4350# label $w.r.f9.l -text "Byte order of sample data:" -width 25 -anchor w 4351# entry $w.r.f9.e -textvar f(byteOrder) -wi 12 4352# pack $w.r.f9.l $w.r.f9.e -side left 4353 4354 pack [checkbutton $w.r.b5 -text "Use audio server at:" -var v(remote)] -pady 10 4355 pack [frame $w.r.f13] 4356 label $w.r.f13.l1 -text "Host" -width 4 4357 entry $w.r.f13.e1 -textvar v(ashost) -wi 20 4358 label $w.r.f13.l2 -text "Port" -width 4 4359 entry $w.r.f13.e2 -textvar v(asport) -wi 5 4360 pack $w.r.f13.l1 $w.r.f13.e1 $w.r.f13.l2 $w.r.f13.e2 -side left 4361 4362# pack [label $w.r.l5 -text "Browser command:"] -pady 5 4363# pack [frame $w.r.f16] 4364# entry $w.r.f16.e -textvar v(browser) -wi 30 4365# pack $w.r.f16.e -side left 4366 4367 pack [label $w.r.l6 -text "Initial path:"] 4368 pack [frame $w.r.f14] 4369 entry $w.r.f14.e -textvar f(ipath) -wi 30 4370 pack $w.r.f14.e -side left 4371 4372 pack [label $w.r.l7 -text "Initial http:"] 4373 pack [frame $w.r.f15] 4374 entry $w.r.f15.e -textvar f(ihttp) -wi 30 4375 pack $w.r.f15.e -side left 4376 4377 pack [frame $w.r.f] -anchor e -pady 5 -padx 5 -side bottom 4378 pack [button $w.r.f.okB -text OK -wi 6 -command {Redraw;destroy .dim}] -side right 4379 pack [button $w.r.f.appB -text Apply -wi 6 -command Redraw] -side right 4380 pack [button $w.r.f.exitB -text Cancel -command {Reset;DrawSect;Redraw;destroy .dim}] -side right 4381 update 4382 4383 if {$v(linkfile) && $f(sndfile) != ""} { 4384 .dim.ll.c create waveform 0 0 -sound snd -height $v(waveh) -width 200 \ 4385 -pixels $v(pps) -tags [list wave both] -start $start \ 4386 -channel $v(vchan) -fill $v(fg) -frame yes -debug 0 \ 4387 -shapefile [file rootname [file tail $f(spath)$f(sndfile)]].shape 4388 } else { 4389 .dim.ll.c create waveform 0 0 -sound snd -height $v(waveh) -width 200 \ 4390 -pixels $v(pps) -tags [list wave both] -start $start \ 4391 -channel $v(vchan) -fill $v(fg) -frame yes -debug 0 4392 } 4393 if {$v(spegh) > 0} { 4394 .dim.ll.c create spectrogram 0 $v(waveh) -sound snd -fftlen $v(fftlen)\ 4395 -height $v(spegh) -width 200 -pixels $v(pps) \ 4396 -preemph $v(preemph) -topfr $v(topfr) \ 4397 -start $start -tags [list speg both] \ 4398 -contrast $v(contrast) \ 4399 -brightness $v(brightness) -gridtspacing $v(gridtspacing) \ 4400 -gridfspacing $v(gridfspacing) -channel $v(vchan) \ 4401 -colormap $v($v(cmap)) -gridcol $v(gridcolor) 4402 } 4403} 4404 4405proc Plugins {} { 4406 global v 4407 4408 set w .plugins 4409 catch {destroy $w} 4410 toplevel $w 4411 wm title $w {Plug-ins} 4412 4413 pack [ label $w.lPlugins -text "Installed plug-ins:"] 4414 pack [ frame $w.f] -fill both -expand true 4415 pack [ scrollbar $w.f.scroll -command "$w.f.list yview"] -side right -fill y 4416 listbox $w.f.list -yscroll "$w.f.scroll set" -setgrid 1 -height 6 -width 50 4417 pack $w.f.list -side left -expand true -fill both 4418 foreach e $v(pluginfiles) { 4419 $w.f.list insert end $e 4420 } 4421 4422 pack [ label $w.lDesc -text Description:] 4423 pack [ frame $w.f2] -fill x 4424 pack [ text $w.f2.text -height 4 -wrap word] -fill x -expand true 4425 4426 pack [ frame $w.f3] 4427 pack [ button $w.f3.b1 -text Load... -command "PluginsAdd $w"] -side left 4428 pack [ button $w.f3.b2 -text Unload -command "PluginsRemove $w"] -side left 4429 pack [ button $w.f3.b3 -text Close -command [list destroy $w]] -side left 4430 4431 bind $w.f.list <ButtonRelease-1> {.plugins.f2.text delete 0.0 end;.plugins.f2.text insert end [namespace inscope [lindex $v(plugins) [.plugins.f.list curselection]] Describe]} 4432} 4433 4434proc PluginsAdd {w} { 4435 global v 4436 4437 set types { 4438 {{xs Plug-in Files} {.plg}} 4439 {{Tcl Files} {.tcl}} 4440 {{All Files} * } 4441 } 4442 set file [tk_getOpenFile -title "Select plug-in" -filetypes $types] 4443 if {$file == ""} return 4444 if {[source $file] == "fail"} return 4445 $w.f.list insert end $file 4446 set v(pluginfiles) [$w.f.list get 0 end] 4447} 4448 4449proc PluginsRemove {w} { 4450 global v 4451 4452 set i [$w.f.list curselection] 4453 namespace inscope [lindex $v(plugins) $i] Unload 4454 set v(plugins) [lreplace $v(plugins) $i $i] 4455 catch {$w.f.list delete $i} 4456 set v(pluginfiles) [$w.f.list get 0 end] 4457 $w.f2.text delete 0.0 end 4458} 4459 4460proc Print {canvas h} { 4461 global v 4462 4463 set w .print 4464 catch {destroy $w} 4465 toplevel $w 4466 wm title $w {Printer setup} 4467 4468 set v(lastpage) [expr int(($v(width)+999)/1000)] 4469 set v(firstpage) 1 4470 4471 frame $w.f1 4472 label $w.f1.l1 -text "Pages:" 4473 entry $w.f1.e1 -textvar v(firstpage) -width 3 4474 label $w.f1.l2 -text "to" 4475 entry $w.f1.e2 -textvar v(lastpage) -width 3 4476 pack $w.f1.l1 $w.f1.e1 $w.f1.l2 $w.f1.e2 -side left 4477 4478 frame $w.f2 4479 label $w.f2.l1 -text "Print command:" -wi 16 4480 entry $w.f2.e1 -textvar v(printcmd) -wi 40 4481 button $w.f2.b1 -text Print -command [list DoPrint print $canvas $h] -wi 8 4482 pack $w.f2.l1 $w.f2.e1 $w.f2.b1 -side left 4483 bind $w.f2.e1 <Key-Return> [list DoPrint print $canvas $h] 4484 4485 frame $w.f3 4486 label $w.f3.l1 -text "Preview command:" -wi 16 4487 entry $w.f3.e1 -textvar v(gvcmd) -wi 40 4488 button $w.f3.b1 -text Preview -command [list DoPrint preview $canvas $h] \ 4489 -wi 8 4490 pack $w.f3.l1 $w.f3.e1 $w.f3.b1 -side left 4491 bind $w.f3.e1 <Key-Return> [list DoPrint preview $canvas $h] 4492 4493 frame $w.f4 4494 label $w.f4.l1 -text "Save to ps-file:" -wi 16 4495 entry $w.f4.e1 -textvar v(psfilet) -wi 40 4496 button $w.f4.b1 -text Save -command [list DoPrint save $canvas $h] -wi 8 4497 pack $w.f4.l1 $w.f4.e1 $w.f4.b1 -side left 4498 bind $w.f4.e1 <Key-Return> [list DoPrint save $canvas $h] 4499 4500 frame $w.f 4501 label $w.f.lab -text "" -width 1 -relief sunken -bd 1 -anchor w 4502 pack $w.f.lab -side left -expand yes -fill x 4503 button $w.f.exitB -text Close -command [list destroy $w] 4504 pack $w.f.exitB -side left 4505 pack $w.f1 $w.f2 $w.f3 $w.f4 $w.f -side top -fill x 4506} 4507 4508proc DoPrint {type c canvh} { 4509 global v 4510 4511 set n 0 4512 set pageno 0 4513 set x 0 4514 if {$c == ".sect.c"} { 4515 set w 1000 4516 } else { 4517 set w $v(width) 4518 } 4519 set title [InfoStr path] 4520 set time [clock format [clock seconds] -format "%a %b %d %T"] 4521 set width 1020 4522 set skip 1000 4523 4524 if {$canvh == -1} { 4525 set canvh $v(toth) 4526 } 4527 4528 $c delete ch1 ch2 sm 4529 $c itemconf relmarkux -stipple "" 4530 4531 while {$w > 0} { 4532 incr pageno 4533 if {$pageno >= $v(firstpage)} { 4534 if {$pageno > $v(lastpage)} break 4535 $c create text [expr $x + 10] -10 -text "$title Page: $pageno of $v(lastpage) Printed: $time" -anchor w -tags decor 4536 if {$c != ".sect.c"} { 4537 $c create line $x 0 $x $canvh -tags decor 4538 if {$w < $width} { 4539 set ww [expr $x + $w] 4540 } else { 4541 set ww [expr $x + $width] 4542 } 4543 $c create line $ww 0 $ww $canvh -tags decor 4544 snack::frequencyAxis $c $x [expr $v(waveh)-1] $v(yaxisw) \ 4545 $v(spegh)\ 4546 -topfrequency $v(topfr) -tags decor -fill $v(fg) 4547 } 4548 $c postscript -file _xspr$n.ps -colormode mono -rotate true -x $x -y -20 -width $width -height [expr $canvh + 20] -pagewidth 26c 4549 4550 switch $type { 4551 print { 4552 regsub {\$FILE} $v(printcmd) _xspr$n.ps cmd 4553 } 4554 preview { 4555 regsub {\$FILE} $v(gvcmd) _xspr$n.ps cmd 4556 } 4557 save { 4558 regsub {\$FILE} $v(psfilecmd) _xspr$n.ps cmd 4559 regsub {\$N} $v(psfilet) $n v(psfile) 4560 } 4561 } 4562 eval exec $cmd 4563 file delete _xspr$n.ps 4564 incr n 4565 $c delete decor 4566 } 4567 incr x $skip 4568 incr w -$skip 4569 } 4570 if {$n == 1} { 4571 SetMsg "Printed 1 page" 4572 } else { 4573 SetMsg "Printed $n pages" 4574 } 4575 DrawCrossHairs 4576 $c itemconf relmarkux -stipple gray50 4577} 4578 4579menu .popmenu -tearoff false 4580proc PopUpMenu {X Y x y} { 4581 global v 4582 4583 .popmenu delete 0 end 4584 4585 if {$y < [expr $v(waveh) + $v(spegh) + $v(timeh)]} { 4586 .popmenu add command -label "Play Range" -command [list PlayMark $x] 4587 } else { 4588 .popmenu add command -label "Play Label" -command [list PlayLabel $x $y] 4589 .popmenu add command -label "Mark Label" -command [list MarkLabel $x $y] 4590 } 4591 .popmenu add command -label "Save Range" -command SaveMark 4592 .popmenu add command -label "Mark Start" -command "PutMarker m1 $x 0 1;SendPutMarker m1 $x" 4593 .popmenu add command -label "Mark End" -command "PutMarker m2 $x 0 1;SendPutMarker m2 $x" 4594 .popmenu add command -label "Zoom" -command OpenZoomWindow 4595 if {$y > [expr $v(waveh) + $v(spegh) + $v(timeh)]} { 4596 .popmenu add command -label "Insert Label" -command [list InsertLabel $x $y] 4597 .popmenu add command -label "Delete Label" -command [list DeleteLabel $x $y] 4598 .popmenu add command -label "Align Label" -command [list AlignLabel $x $y] 4599 .popmenu add command -label "Get Right Label" -command [list GetRightLabel $x $y] 4600 } 4601 catch {tk_popup .popmenu $X $Y 0} 4602} 4603 4604proc SaveSettings {} { 4605 global v f s 4606 4607 if [catch {open [file join ~ .xsrc] w} out] { 4608 SetMsg $out 4609 } else { 4610 puts $out "set v(s_version) $v(p_version)" 4611 puts $out "set v(waveh) $v(waveh)" 4612 puts $out "set v(spegh) $v(spegh)" 4613# puts $out "set v(scrw) $v(scrw)" 4614 puts $out "set v(pps) $v(pps)" 4615 puts $out "set v(fftlen) $v(fftlen)" 4616 puts $out "set v(winlen) $v(winlen)" 4617 puts $out "set v(anabw) $v(anabw)" 4618 puts $out "set v(preemph) $v(preemph)" 4619 puts $out "set v(ipa) $v(ipa)" 4620 puts $out "set v(autoload) $v(autoload)" 4621 puts $out "set v(ch) $v(ch)" 4622 puts $out "set v(slink) $v(slink)" 4623 puts $out "set v(mlink) $v(mlink)" 4624 puts $out "set v(printcmd) \{$v(printcmd)\}" 4625 puts $out "set v(gvcmd) \{$v(gvcmd)\}" 4626 puts $out "set v(pluginfiles) {$v(pluginfiles)}" 4627# puts $out "set v(browser) \{$v(browser)\}" 4628 puts $out "set v(rate) $v(rate)" 4629 puts $out "set v(sfmt) $v(sfmt)" 4630 puts $out "set v(chan) $v(chan)" 4631# puts $out "set v(offset) $v(offset)" 4632# puts $out "set v(zerolabs) $v(zerolabs)" 4633 puts $out "set v(ipafmt) $v(ipafmt)" 4634 puts $out "set v(labalign) $v(labalign)" 4635 puts $out "set v(fg) $v(fg)" 4636 puts $out "set v(bg) $v(bg)" 4637 puts $out "set v(fillmark) $v(fillmark)" 4638 puts $out "set v(font) \{$v(font)\}" 4639 puts $out "set v(sfont) \{$v(sfont)\}" 4640 puts $out "set v(gridfspacing) $v(gridfspacing)" 4641 puts $out "set v(gridtspacing) $v(gridtspacing)" 4642 puts $out "set v(gridcolor) $v(gridcolor)" 4643 puts $out "set v(remote) \{$v(remote)\}" 4644 puts $out "set v(ashost) \{$v(ashost)\}" 4645 puts $out "set v(asport) \{$v(asport)\}" 4646 puts $out "set v(recording) \{$v(recording)\}" 4647 puts $out "set v(cmap) \{$v(cmap)\}" 4648 puts $out "set v(showspeg) \{$v(showspeg)\}" 4649 puts $out "set v(linkfile) \{$v(linkfile)\}" 4650 4651 puts $out "set f(skip) $f(skip)" 4652 puts $out "set f(ipath) $f(ipath)" 4653 puts $out "set f(ihttp) $f(ihttp)" 4654 4655 puts $out "set s(fftlen) $s(fftlen)" 4656 puts $out "set s(anabw) $s(anabw)" 4657 puts $out "set s(wintype) $s(wintype)" 4658 puts $out "set s(ref) $s(ref)" 4659 puts $out "set s(range) $s(range)" 4660 puts $out "set s(atype) $s(atype)" 4661 puts $out "set s(lpcorder) $s(lpcorder)" 4662 4663 if {[info exists snack::snackogg]} { 4664 puts $out "set ogg(nombr) $::ogg(nombr)" 4665 puts $out "set ogg(maxbr) $::ogg(maxbr)" 4666 puts $out "set ogg(minbr) $::ogg(minbr)" 4667 puts $out "set ogg(com) $::ogg(com)" 4668 puts $out "set ogg(query) $::ogg(query)" 4669 } 4670 4671 close $out 4672 } 4673} 4674 4675proc SetCursor {flag} { 4676 foreach widget [winfo children .] { 4677 $widget config -cursor $flag 4678 } 4679 update idletasks 4680} 4681 4682# Put custom procedures between the lines below 4683# Custom procs start here 4684# Custom procs end here 4685 4686foreach plug [split $v(pluginfiles)] { 4687 source $plug 4688} 4689 4690DrawCrossHairs 4691ToggleRecording 4692Link2File 4693 4694if {$tcl_platform(platform) == "windows"} { 4695 update idletasks 4696 Redraw 4697} 4698 4699proc GetStdin {} { 4700 global v pipevar 4701 4702 append pipevar [read -nonewline stdin] 4703 if [eof stdin] { 4704 fileevent stdin readable "" 4705 if {$pipevar != ""} { 4706 snd data $pipevar 4707 set v(rate) [snd cget -rate] 4708 set v(sfmt) [snd cget -encoding] 4709 set v(chan) [snd cget -channels] 4710 wm geometry . {} 4711 Redraw 4712 event generate .cf.fc.c <Configure> 4713 MarkAll 4714 PlayAll 4715 } 4716 } 4717} 4718 4719if [info exists demoFlag] { 4720 OpenFiles [file join [pwd] ex2.wav] 4721 OpenFiles [file join [pwd] ex2.phn] 4722 return 4723} 4724if {$argv == "-"} { 4725 fconfigure stdin -translation binary -blocking 0 4726 if {$tcl_version > 8.0} { 4727 fconfigure stdin -encoding binary 4728 } 4729 fileevent stdin readable GetStdin 4730} elseif [llength $argv] { 4731 if {[llength $argv] > 1} { set v(autoload) 0 } 4732 foreach file $argv { 4733 OpenFiles $file 4734 } 4735} else { 4736 if [string compare macintosh $::tcl_platform(platform)] { 4737 GetOpenFileName 4738 } 4739} 4740