Stupid Mac::Glue Tricks: PODxt Sampling

| | Comments (0)
The PODxt guitar amp/fx modeler was recently updated with a bunch of new stuff, including a bass expansion pack. Well, I play bass and guitar, and I liked the idea of not having to buy a Bass PODxt to go with my regular one. So I got the expansion pack to test it out, and wrote this program to do it. It requires the following steps, apart from having all the proper modules and software installed:
  • Create glues for QuickTime Player, MidiPipe, and Sound Studio (the latter only if you want to record the result)
  • Set your default audio output to the PODxt
  • If recording, set Sound Studio's audio input to the PODxt
  • In System Preferences, set the PODxt to do reamping (cmd-3)
  • Create a MidiPipe file that has a MIDI In named 'MidiPipe Input 1' and has MIDI Out set to the PODxt, and save it in the same directory as this program, with a '.mipi' extension
  • In main_loop(), set the programs you want to try out; the demo here first loops over some programs, then switches to a blank program, then tries out a bunch of different amps by themselves
  • If you want each program to be announced with speech, set the $SPEECH variable to true
  • Run the program, as 'podxt-soundtest.plx path/to/someaudiofile.aif', where the audio file is a recording of clean guitar/bass; it will save the files in 'path/to/someaudiofile-samples/'
That's basically it. It will play the given sound file through the PODxt for each program or amp you tell it you want to hear. This can easily be extended to also sample anything else in the PODxt: different effects, different settings for the effects, and so on, using the MIDI CC Reference guide (for example, amp changes are CC #11, stomp box changes are CC #75, modulation changes are CC #58, etc.). I figure I will use this quite a bit as I pick up recording again soon, so I can quickly and easily sample different amps and effects to find the sound I want.

# podxt-soundtest.plx
use strict;
use warnings;

use File::Basename;
use File::Spec::Functions qw(catdir catfile);
use FindBin '$Bin';
use Mac::Errors '$MacError';
use Mac::Glue ':all';
use Mac::Speech;
use Time::HiRes 'sleep';

my $DEBUG = 1;
my $RECORD = 1;
my $SPEECH = 0;

use constant {
    CC        => 176,
    PROGRAM        => 192,

    AMP_ENABLE    => 111,
    AMP_SELECT    => 11,

my @voice = qw(Damien Diane Vicki Victoria);
my $midi_port  = 'MidiPipe Input 1';
my $sound_file = shift;
my($sound_name, $sound_dir) = fileparse($sound_file, qr/\..+/);
my($qt_player, $midi_pipe, $sound_studio, $voice, $speech, $recording, $movie, $done);


sub main_loop {
    for my $n (111, 32 .. 79) {
        doit(program => $n);

    # blank program
    midi({ program => 127 });

    for my $n (73 .. 100) {
        doit(amp => $n);

sub doit {
    my($what, $which) = @_;

    say($what, $which);
    midi({ $what, $which });

    save_recording($what, $which);

sub finish {
    print "Done.\n";

sub init {
    $qt_player  = new Mac::Glue 'QuickTime Player';
    $midi_pipe  = new Mac::Glue 'MidiPipe';
    $sound_studio = new Mac::Glue 'Sound Studio' if $RECORD;

    if ($SPEECH) {
        my $V;
        for (@voice) {
            last if $V = $Mac::Speech::Voice{$_};
        $speech = NewSpeechChannel( $V );

    if ($DEBUG) {
        $sound_studio->ERRORS(1) if $RECORD;

    $sound_studio->launch if $RECORD;

    my($pipe) = fileparse($0, qr/\..+/);
    $midi_pipe->open(catfile($Bin, $pipe . '.mipi'));


    # preload voice
    if ($SPEECH) {
        SpeakText($speech, '');
        sleep 0.1 while SpeechBusy();

    $movie = $qt_player->obj(movie => 1, window => 1);
    $done  = $movie->prop('done');

sub midi {
    my($params) = @_;
    my $opts = {
        toPort    => $midi_port

    if (defined $params->{program}) {
        $opts->{withData} = [ PROGRAM, $params->{program} ];

    } elsif (defined $params->{amp}) {
        $opts->{withData} = [ CC, AMP_ENABLE, 0 ];
        $opts->{withData} = [ CC, AMP_SELECT, $params->{amp} ];


sub say {
    return unless $SPEECH;
    my($what, $which) = @_;

    my $text = "$what number $which";
    print "$text\n";

    midi({ program => 127 });

    SpeakText($speech, $text);
    sleep 0.1 while SpeechBusy();

sub play {
    while (1) {
        last if $done->get;
        sleep 0.5;
    sleep 1.5;

sub get_sound_files {
    if ($RECORD) {
        $recording = $sound_studio->make(new => 'document');


sub open_sound_file {
    $qt_player->obj(file => $sound_file)->open;

sub start_recording {
    return unless $RECORD;

sub stop_recording {
    return unless $RECORD;

sub save_recording {
    return unless $RECORD;
    my($what, $which) = @_;

    my $dir = catdir($sound_dir, $sound_name . '-samples');
    mkdir $dir;

    sleep 5;
        in    => $recording->obj(file => catfile($dir, "$what-$which.aiff")),
        as    => enum('AIFF')
    sleep 5;

Leave a comment

<pudge/*> (pronounced "PudgeGlob") is thousands of posts over many years by Pudge.

"It is the common fate of the indolent to see their rights become a prey to the active. The condition upon which God hath given liberty to man is eternal vigilance; which condition if he break, servitude is at once the consequence of his crime and the punishment of his guilt."

About this Entry

This page contains a single entry by pudge published on April 29, 2006 10:46 AM.

Homo erectus was the previous entry in this site.

DirecTV Lameness is the next entry in this site.

Find recent content on the main index or look in the archives to find all content.