Updated 2010-12-25 18:59:37 by dkf

A Snack based application.

I enjoy talk radio, but some of my favorite shows play when I don't have access to a radio (like when I'm sleeping, for example). I finally got around to enabling the sound card on my UNIX server (Slackware 8 based). I installed the Linux Alsa drivers, which appear to work just fine.

Anyway, I figured I could just connect the Line-out from an available radio into the Line-in of the UNIX server machine, and record the programs. Well, being a Tcl kind of guy, I immediately thought of using Snack. I wanted the output to be in mp3 format, so I also have to use another application (Snack doesn't support mp3 for output). The following is a summary of the process, which might be useful to a few others.

Here are the components that make up my Radio Recorder:

  • cronjob - schedules the recordings. UNIX only, but other platforms have equivalents.
  • Tcl - Needed for Snack. Available for all platforms.
  • Snack - Extension to Tcl. Controls the audio card mixer and reads the Line-in and writes to WAV format. Available for all platforms.
  • lame - An mp3 encoder that converts the WAV output from Snack to mp3 format. Available for all platforms.

Here's the small Tcl program that's the core of the process. Since it's not a Wish application, it does a 'package require sound' instead of 'package require snack'. The snack package includes widgets, so you can't load it into a tclsh application. It sets the gain for the Line-in, reads the Line-in at 16000 sampling (remember, I'm recording talk radio, so this is plenty) and writes to stdout in WAV format. It takes one parameter, the number of seconds to record.
  #!/usr/bin/env tclsh

  package require sound

  set ::left  90
  set ::right 90
   
  snack::mixer volume IGain left right

  snack::sound ss -channel stdout -rate 16000 -channels Mono
  ss record -input Line1 -fileformat WAV

  after [expr [lindex $argv 0] * 1000] exit

  vwait forever

The output from this program is piped through lame to write the final output to an mp3 file. One hour of recording generates a ~10 MB file.

Here is an example shell script that gets run from a crontab entry. It creates a 1 hour time-stamped recording, storing it on a network accessible drive
  #!/bin/sh

  DEST=/mnt/bilbo/windows/MP3/Radio/DougMcIntyre

  TOD=`date +%d%b%Y_%H%M%S`
  exec /usr/local/bin/tclsh $HOME/radio/radiorecorder.tcl 3600 | /usr/local/bin/lame - $DEST/DougMcIntyre$TOD.mp3

That's it. I have various cronjobs that make hours of recordings of my favorite programs. I use Snackamp [1] to play back the radio shows on any of my Windows or UNIX machines. My next step will be to get an AM/FM tuner card that I can install in the server (anyone know of a good one?).

Marty Backe 07 Aug 2002

I've updated the program to take pairs of command line arguments, specifying start and stop times (in seconds). This was done because some of the radio programs I record are syndicated and therefore have precise, dependable commercial breaks. I can have the recording start and stop, thus avoiding the recording of commercials (and helping to reduce file size - a typical 1 hour talk show only requires ~35 minutes of disk space). Marty Backe - 31 Dec 2003
 #!/usr/bin/env tclsh

 package require sound
 
 proc Exit {} {
     ::ss stop
     exit
 }

 #
 # Parse input parameters. Each parameter consists of a start time, colon, and
 # stop time. All times are in seconds, referenced to the program start time.
 #
 if {$argc == 0} {
     puts "ERROR: At least one start/stop time must be provided."
     exit 255
 }
 foreach parameter $argv {
     set     splitList [split $parameter :]
     lappend recordTimesList $splitList
 }
 
 
 set ::left  90
 set ::right 90 
 
 snack::mixer volume IGain left right
 
 snack::sound ss -channel stdout -rate 16000 -channels Mono
 ss record -input Line1 -fileformat WAV
 ss pause
 
 #
 # Create a series of events to start and stop the recording
 #
 foreach times $recordTimesList {
     set startTime [expr {[lindex $times 0] * 1000}]
     set stopTime  [expr {[lindex $times 1] * 1000}] 
 
     after $startTime {ss pause}
     after $stopTime  {ss pause}
 }
 
 #
 # Setup for program exit after the last stop
 #
 set lastTimeIndex [expr {$argc - 1}]
 set exitTime [lindex [lindex $recordTimesList $lastTimeIndex] 1]
 set exitTime [expr {$exitTime * 1000}]
 incr exitTime 10
 after $exitTime Exit
 
 vwait forever

And here's the driver shell (UNIX) script, run from a cronjob.
 #!/bin/sh
 
 DEST=/mnt/bilbo_extra/MP3/Radio/DennisPrager
 
 TOD=`date +%d%b%Y_%H%M%S`
 exec /usr/local/bin/tclsh $HOME/radio/radiorecorder.tcl 330:1025 1265:1805 2060:2405 2645:3125 3320:3530 | /usr/local/bin/lame - $DEST/DennisPrager$TOD.mp3 > /dev/null

For Windows, I use the Task Manager to schedule a batch file to run. Here's an example batch file:
 for /f %%i in ('c:\tcl\bin\tclsh84.exe c:\radio\getDate.tcl') do set DATESTRING=%%i
 
 c:\Tcl\bin\tclsh84.exe c:\radio\radiorecorder.tcl 360:1005 1230:17845 2085:2450 2640:3035 3195:3575 | c:\lame\lame.exe - c:\mp3\radio\TammyBruce\TammyBruce%DATESTRING%.mp3

The first line is a convoluted (but necessary) approach to setting a batch variable (DATESTRING) to the results of another program (a Tcl program that creates the needed date/time string).

Here's the getDate.tcl program:
 puts [clock format [clock -seconds] -format %d%h%Y_%H%M%S]

Marty Backe - 07 Nov 2004

Marty Backe - 27 May 2005 - incorporated a couple of updates suggested by Geoffrey Coram

VPT - 8 June 2005 - If you're using Linux then vsound (http://www.zorg.org/vsound/index.shtml) avoids need for the cable

CJL - 9 June 2005 - The only cable referenced is to connect an external tuner to the line-in. No amount of software could substitute in that role ;-) Were you thinking that the audio source was the servers own line-out? (In that case vsound may help, although I think any modern sound card/driver makes "what-u-hear" and/or "pcm audio" available as a directly recordable source anyway)

VPT - 23 June 2005 - My apologies, I should have read it more carefully. I know someone ;) who uses vsound to capture BBC Radio 7 comedy rebroadcasts using Real player which doesn't let you save the streaming content.

CJL - 24 June 2005 - And I know someone who uses mplayer, lame and a couple of scripts to achieve a similar effect to keep his iPod fed with ISIHAC and the like ;)

CJL further adds... Having just made the move to OSX (Mac Mini running 10.4 with an iMic USB line-in device), I'm finding that snack dies when running even the simplest script on this page (specifically, it generates a 'bus error' and drops me back to my shell) - has anybody had success in this area?

PCO - 18 december 2010 - I succeded in fixing this severe issue. The problem was that input functions weren't implemented at all. As for the input and output gains setting. You can find the full function snack 2.2.10 library here : Snack 2.2.10 and the source code here : Snack 2.2.10_src

See also edit