Page 1 of 1

Creating dynamic audio files with PHP

Posted: Sun Jan 12, 2003 6:04 pm
by skehoe
Hey all,

I'm working on a ascii <-> morse code conversion tool and I'd like to add some audio out capability to it (simple dots and dashes at variable WPM rates). I've seen this done on the perl side, but can't find any audio classes for PHP.

Does anyone know where I can find PHP audio classes or have any pointers on how to do this?

Thanks in advance for any help,

~Scott

Posted: Mon Jan 13, 2003 1:14 am
by mydimension
you might have more luck looking for a module rather than a class to do this seeing as how this funtionality requires a ton of binary handling and frankly php doesn't excel at binary handling (at least not in my experience).

Posted: Mon Jan 13, 2003 12:08 pm
by skehoe
Thanks for the feedback. You seem to be the only one that wanted to touch that one. :)

I've seen this done with pack() / unpack() on perl, but I just don't understand the format of the sound files (au, aiff, etc) well enough to do this and unfortunately I don't know perl well enough to work with the example... I'll keep looking and I'll be sure to post back here if I find anything.

~Scott

Posted: Mon Jan 13, 2003 7:47 pm
by mydimension
here is a site that may help you with the file formats: http://www.wotsit.org/
i ran across it a while ago will doing some VB programming. forget what i was looking for but it has stayed in by bookmarks ever since. now i pass it on to you.

Creating dynamic audio files with PHP

Posted: Mon Jan 13, 2003 8:17 pm
by fractalvibes
Here is site that may not directly be a help:
http://lame.sourceforge.net/

But I'll bet you might can get some direction there.

You might be better off having some pre-recorded sounds - a dot and a dash for instance,as Windows Media clips, for example, and invoking these
as needed - see : http://www.txfb.org/AgClass/resource/AITCrg4.asp
and view source as an idea.

Yet another idea is to look here : http://reglos.de/musinum/InternetMusic.html

I see the site is in transition now - but bookmark that - lots of fun and perhaps another idea. He is using Java to interactively create a MIDI file,
perhaps a best solution, as MIDI is quite small - liken MIDI to a Vector Graphics language for music when comparing with Audio...

Phil J.

Posted: Tue Jan 14, 2003 1:34 am
by skehoe
Thanks for the suggestions!

This has been an interesting challenge and everything helps. I'll be sure to update this thread if I ever get anything working.

~Scott

Posted: Wed Jan 15, 2003 6:37 am
by skehoe
I got it to work. With PHP. :D

If anyone is interested in the code, PM me and I'll send it to you.

Once again, thanks for all the suggestions.

~Scott

Posted: Wed Jan 15, 2003 11:46 am
by llimllib
I'm interested...why don't you just post the code here so anyone reading the forums can see it?

Posted: Wed Jan 15, 2003 12:50 pm
by skehoe
...Wasn't sure if anyone would be interested.

It's not pretty and not optimized (haven't had any more time to hack on it since early this AM when I got it to work), but it works. :)

Note: you should create a directory 'temp' in the same directory you run it from that has full rw access.

~Scott

Code: Select all

<?

// morse.php
// skehoe - 1.11.03

$morse = array(
	'0'	=>	'-----',
	'1'	=>	'.----',
	'2'	=>	'..---',
	'3'	=>	'...--',
	'4'	=>	'....-',
	'5'	=>	'.....',
	'6'	=>	'-....',
	'7'	=>	'--...',
	'8'	=>	'---..',
	'9'	=>	'----.',
	'A'	=>	'.-',
	'B'	=> 	'-...',
	'C'	=>	'-.-.',
	'D'	=>	'-..',
	'E'	=>	'.',
	'F'	=>	'..-.',
	'G'	=>	'--.',
	'H'	=>	'....',
	'I'	=>	'..',
	'J'	=>	'.---',
	'K'	=>	'-.-',
	'L'	=>	'.-..',
	'M'	=>	'--',
	'N'	=>	'-.',
	'O'	=>	'---',
	'P'	=>	'.--.',
	'Q'	=>	'--.-',
	'R'	=>	'.-.',
	'S'	=>	'...',
	'T'	=>	'-',
	'U'	=>	'..-',
	'V'	=>	'...-',
	'W'	=>	'.--',
	'X'	=>	'-..-',
	'Y'	=>	'-.--',
	'Z'	=>	'--..',
	'PERIOD'	=>	'.-.-.-',
	'COMMA'		=>	'--..--',
	'COLON'		=>	'---...',
	'QUESTION'	=>	'..--..',
	'APOS'		=>	'.----.',
	'HYPHEN'	=>	'-....-',
	'PAREN'		=>	'-.--.-',
	'QUOTE'		=>	'.-..-.',
	'SLASH'		=>	'-..-.',
	'SEMI'		=>	'-.-.-',
	'UNDER'		=>	'..--.-',
	'SPACE'		=>	'/'
);

function create_sound($in) {
    $length = array(
        'dash'      =>  3,
        'pause1'    =>  1,
        'pause2'    =>  3,
        'pause3'    =>  7,
        'word'      =>  50,
        'dot'       =>  1000 * 60 / ($in[wpm] * 50)          
    );

    $pieces = preg_split('//', $in

Code: Select all

);

    $count[dot] = 0;
    $count[dash] = 0;    
    $count[space] = 0;
    $count[slash] = 0;

    foreach ($pieces as $key => $val) {
        if ($val == '.') {
            $count[dot]++;
        } else if ($val == '-') {
            $count[dash]++;
        } else if ($val == ' ') {   
            $count[space]++;
        } else if ($val == '/') {
            $count[slash]++;
        }
    }

    // Sound Header
    $bytes = $length[dot] * 8 * ($count[dot] * (1 + $length[pause1])
             + $count[dash] * ($length[dash] + $length[pause1])
             + $count[space] * ($length[pause2] - $length[pause1])
             + $count[slash] * ($length[pause3] - $length[pause1]));
   
    $sound .= pack(H8,"2e736e64"); // magic number
    $sound .= pack(H8,"0000001c"); // data location (=28)
    $b1 = ($bytes & (255 << 24)) >> 24;
    $b2 = ($bytes & (255 << 16)) >> 16;
    $b3 = ($bytes & (255 << 8)) >> 8;
    $b4 = $bytes & (255);
    $sound .= pack(C4,$b1,$b2,$b3,$b4);
    $sound .= pack(H8,"00000002"); // sound type - 8bit linear
    $sound .= pack(H8,"00001f40"); // sampling rate
    $sound .= pack(H8,"00000001"); // channel count
    $sound .= pack(H8,"00000000"); // optional info (minimum 4 bytes)

    foreach ($pieces as $key => $val) {
        if ($val == '.') {
            $sound .= sound_data(1,1,$length);
            $sound .= sound_data($length[pause1],0,$length);
        } else if ($val == '-') {
            $sound .= sound_data($length[dash],1,$length);
            $sound .= sound_data($length[pause1],0,$length);
        } else if ($val == ' ') {
            $sound .= sound_data($length[pause2] - $length[pause1],0,$length);
        } else if ($val == '/') {
            $sound .= sound_data($length[pause3] - $length[pause1],0,$length);
        }
    }
	return $sound;
}

function sound_data($units,$onoff,$length) {
    $sound = pack(H16,"a781a700597f5900");
    $no_sound = pack(H16,"0000000000000000");
    if ($onoff == '1') {
        $out = $sound;
    } else {
        $out = $no_sound;
    }
    for ($count = $length[dot] * $units; $count > 0; $count--) {
        $return .= $out;
    }
	return $return;	
}

function check_punct($val) {
	// Replace with case
	if ($val == '.') { $val = 'PERIOD'; }
    else if ($val == ',') { $val = 'COMMA'; }
    else if ($val == ':') { $val = 'COLON'; }
    else if ($val == '?') { $val = 'QUESTION'; }
    else if ($val == "'") { $val = 'APOS'; }
    else if ($val == '-') { $val = 'HYPHEN'; }
    else if ($val == '(') { $val = 'PAREN'; }
    else if ($val == ')') { $val = 'PAREN'; }
    else if ($val == '"') { $val = 'QUOTE'; }
	else if ($val == '/') { $val = 'SLASH'; }
	else if ($val == ';') { $val = 'SEMI'; }
	else if ($val == '_') { $val = 'UNDER'; }
    else if ($val == ' ') { $val = 'SPACE'; }
	else if ($val == 'COMMA') { $val = ','; }
	else if ($val == 'PERIOD') { $val = '.'; }
	else if ($val == 'COLON') { $val = ':'; }
	else if ($val == 'QUESTION') { $val = '?'; }
	else if ($val == 'APOS') { $val = "'"; }
	else if ($val == 'HYPHEN') { $val = '-'; }
	else if ($val == 'PAREN') { $val = '('; }
	else if ($val == 'QUOTE') { $val = '"'; }
	else if ($val == 'SLASH') { $val = '/'; }
	else if ($val == 'SEMI') { $val = ';'; }
	else if ($val == 'UNDER') { $val = '_'; }
	else if ($val == 'SPACE') { $val = ' '; } 
	return $val;
}

function ascii_to_morse($in, $morse) {
	$clean = str_replace('  ', ' ', $in);
	$in_array = preg_split('//', strtoupper($clean), -1, PREG_SPLIT_NO_EMPTY); 
	foreach ($in_array as $key => $val) {
		$out[input] .= $val;
		$val = check_punct($val);
		$out[output] .= $morse[$val]." ";
	}	
	return $out;
}

function morse_to_ascii($in, $morse) {
	$in_array = split(' ', $in);	
	foreach ($in_array as $key => $val) {
		$out[input] .= $val." ";
		foreach ($morse as $foo => $bar) {
			if ($bar == $val) {
				$foo = check_punct($foo);	
				$out[output] .= $foo;
				break;
			}
		}
	}
	// Check for open and close parens...
	
	return $out;
}

function display_main($in, $listen, $wpm) {
?>
	<center>
	<h2>Morse Code Translator</h2>
	<form method="post" action="index.php">
	<b>Enter Text or Morse Code Here:</b><br>
	<font color="blue">Acceptable Entries: A-Z 0-9 . , : ; ? ' " - _ / ( )</font><br>
	<br><textarea name="user_in" rows="10" cols="80"></textarea><br>
	<br><b>Text to Morse&nbsp;</b><input type="radio" name="type" value="t_to_m" checked>&nbsp;&nbsp;<b>Morse to Text&nbsp;<input type="radio" name="type" value="m_to_t">
	&nbsp;&nbsp;<b>WPM: </b><input type="text" size="5" name="wpm" value="15"><br>
	<br><input type="submit" value="Translate Now">
	</form>
<?
	if (is_array($in)) {
		echo "<p><hr><b><u>Your Text/Code</u></b><br><br>".stripslashes($in[input]);
        echo "<p><hr><b><u>Translation</u></b><br><br>".stripslashes($in[output])."<br><br>";
		if ($listen == 1) {
			$out

Code: Select all

= $in[output];
			$out[wpm] = $wpm;
			$sound = create_sound($out);
			create_file($sound);
			echo '<embed src="temp/morse.au" volume="50" autostart="false" height="15" width="300"><br>';
		}
		echo "<br><hr>";
    } 
}

function create_file($sound) {
	$filename = 'temp/morse.au';
	$fp = fopen($filename, 'w+');
	fwrite($fp, $sound);
	fclose($fp);
}

// MAIN

$out = '';
$listen = 0;

if (isset($_POST[user_in])) {
    if ($_POST[type] == 'm_to_t') {
        $out = morse_to_ascii($_POST[user_in], $morse);
    } else if ($_POST[type] == 't_to_m') {
        $out = ascii_to_morse($_POST[user_in], $morse);
        $listen = 1;
    }
}

display_main($out, $listen, $_POST[wpm]);

?>

Posted: Wed Jan 15, 2003 12:53 pm
by skehoe
Sorry about the indentation on that... It seems to have disappeared when I pasted the code.

Posted: Wed Jan 15, 2003 2:18 pm
by llimllib
no problem...very cool stuff, nice hack