Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Chriss Miller on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Writing a super easy WAVE file from scratch.

Status
Not open for further replies.

xoedusk

Programmer
Joined
Jul 26, 2007
Messages
5
Location
US
Hello all. I'm attempting to do create a wave file from scratch. I've searched online and understand the WAVE file format. Now I'm trying to load up all the necessary bytes into an array, and print the array to a binary file. Here's what it looks like so far:

Code:
#!/usr/bin/perl


@array=(0x52,0x49,0x46,0x46,0x40,0x00,0x00,0x00,0x57,0x41,0x56,0x45,0x66,0x6d,0x74,0x20,0x10,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
0x40,0x1f,0x00,0x00,0x40,0x1f,0x00,0x00,0x01,0x00,0x08,0x00,0x64,0x61,0x74,0x61,0x1c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x24,0x17,0x1e,0xf3,0x3c,0x13,0x3c,0x14,0x16,0xf9,0x18,0xf9,0x34,0xe7,0x23,0xa6,0x3c,0xf2,0x24,0xf2,0x11,0xce,0x1a,0x0d);

open(FILE, ">play.wav") or die "Error opening play.wav: $!\n";
binmode FILE;
print FILE @array;
close FILE;

Needles to say it doens't work. I try to play it in iTunes, and it doesn't work. Opening it in Praat gives me an error "File not finished."

Any ideas?
 
Try:

Code:
print FILE join ("",@array);

Calling @array in the context you were is gonna do one of two things... either insert scalar(@array), or the number of elements in the array... or join all the array elements with the space character. Neither is probably what you want.

-------------
Cuvou.com | My personal homepage
Project Fearless | My web blog
 
Thank you for replying. Both ways of printing produce the same .wave file. This is the wave file when I open it in a text editor:

827370706400087658669102109116321600010106431006431001080100971169728000000036233024360196020222492424952231351666024236242172062613

Is it a valid way to produce a binary file in the way I am doing it? That is, store the individual bytes in an array, and print the array to the binary file? I'm guessing if that is okay, then its just the hex bytes I store in the array that are messed up.
 
The pack didn't seem to do the trick. Should I include the file handle still in the command?
 
There almost certainly is a way to do this using pack as prex1 suggested, but here's a simple way to do it using chr.

Note how I've reformatted your data into hex strings instead of hex numbers. This makes it a lot easier to see what data your importing. And if you have an hex editor, easy to compare with the final result.

Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]@array[/blue] = [red]qw([/red][purple][/purple]
[purple]	52 49 46 46 40 00 00 00  57 41 56 45 66 6d 74 20[/purple]
[purple]	10 00 00 00 01 00 01 00  40 1f 00 00 40 1f 00 00[/purple]
[purple]	01 00 08 00 64 61 74 61  1c 00 00 00 00 00 00 00[/purple]
[purple]	24 17 1e f3 3c 13 3c 14  16 f9 18 f9 34 e7 23 a6[/purple]
[purple]	3c f2 24 f2 11 ce 1a 0d[/purple]
[purple][/purple][red])[/red][red];[/red]

[black][b]my[/b][/black] [blue]$wavfile[/blue] = [red]'[/red][purple]play.wav[/purple][red]'[/red][red];[/red]
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]FILE, [red]"[/red][purple]>[blue]$wavfile[/blue][/purple][red]"[/red][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Can't open [blue]$wavfile[/blue]: [blue]$![/blue][/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/binmode.html][black][b]binmode[/b][/black][/url] FILE[red];[/red]
[olive][b]foreach[/b][/olive] [red]([/red][blue]@array[/blue][red])[/red] [red]{[/red]
	[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] FILE [url=http://perldoc.perl.org/functions/chr.html][black][b]chr[/b][/black][/url][red]([/red][url=http://perldoc.perl.org/functions/hex.html][black][b]hex[/b][/black][/url][red]([/red][blue]$_[/blue][red])[/red][red])[/red][red];[/red]
[red]}[/red]
[url=http://perldoc.perl.org/functions/close.html][black][b]close[/b][/black][/url] FILE[red];[/red]

- Miller
 
Thank you very much - I will give that a try once I get home.
 
Thank you, Miller. That worked! Don't hear much obviously, but the wave file appears to play on my computer. Weird.
 
Well of course it worked. ;)

Btw, that print line could also have been done with pack using the following:

Code:
[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] FILE [url=http://perldoc.perl.org/functions/pack.html][black][b]pack[/b][/black][/url] [red]"[/red][purple]C[/purple][red]"[/red], [url=http://perldoc.perl.org/functions/hex.html][black][b]hex[/b][/black][/url][red]([/red][blue]$_[/blue][red])[/red][red];[/red]

However, I think that chr is more clear anyway.

- Miller
 
Also, in case you or anyone else would wish to reverse that result, the following code would work. I can imagine a situation where someone might wish to embed a sound in the source code, so this would be a useful way to that. Obviously, not as compact as the raw bytes, but maybe serves it's own purpose.

Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]$wavfile[/blue] = [red]'[/red][purple]play.wav[/purple][red]'[/red][red];[/red]
[url=http://perldoc.perl.org/functions/open.html][black][b]open[/b][/black][/url][red]([/red]FILE, [red]"[/red][purple][blue]$wavfile[/blue][/purple][red]"[/red][red])[/red] or [url=http://perldoc.perl.org/functions/die.html][black][b]die[/b][/black][/url] [red]"[/red][purple]Can't open [blue]$wavfile[/blue]: [blue]$![/blue][/purple][red]"[/red][red];[/red]
[url=http://perldoc.perl.org/functions/binmode.html][black][b]binmode[/b][/black][/url] FILE[red];[/red]
[black][b]my[/b][/black] [blue]$col[/blue] = [fuchsia]0[/fuchsia][red];[/red]
[olive][b]while[/b][/olive] [red]([/red]<FILE>[red])[/red] [red]{[/red]
	[black][b]my[/b][/black] [blue]@array[/blue] = [url=http://perldoc.perl.org/functions/unpack.html][black][b]unpack[/b][/black][/url] [red]"[/red][purple]C*[/purple][red]"[/red], [blue]$_[/blue][red];[/red]
	
	[gray][i]# Format Output[/i][/gray]
	[olive][b]for[/b][/olive] [black][b]my[/b][/black] [blue]$char[/blue] [red]([/red][blue]@array[/blue][red])[/red] [red]{[/red]
		[url=http://perldoc.perl.org/functions/print.html][black][b]print[/b][/black][/url] [red]'[/red][purple] [/purple][red]'[/red] [olive][b]if[/b][/olive] [blue]$col[/blue] > [fuchsia]7[/fuchsia][red];[/red]
		[black][b]print[/b][/black] [url=http://perldoc.perl.org/functions/sprintf.html][black][b]sprintf[/b][/black][/url] [red]"[/red][purple]%02x[/purple][red]"[/red], [blue]$char[/blue][red];[/red]
		[black][b]print[/b][/black] [red]'[/red][purple] [/purple][red]'[/red] [olive][b]if[/b][/olive] [blue]$col[/blue] < [fuchsia]8[/fuchsia][red];[/red]
		[blue]$col[/blue] = [red]([/red][blue]$col[/blue] + [fuchsia]1[/fuchsia][red])[/red] [blue]%[/blue] [fuchsia]16[/fuchsia][red];[/red]
		[black][b]print[/b][/black] [red]"[/red][purple][purple][b]\n[/b][/purple][/purple][red]"[/red] [olive][b]if[/b][/olive] ![blue]$col[/blue][red];[/red]
	[red]}[/red]
[red]}[/red]
[black][b]print[/b][/black] [red]"[/red][purple][purple][b]\n[/b][/purple][/purple][red]"[/red] [olive][b]if[/b][/olive] [blue]$col[/blue][red];[/red]

[url=http://perldoc.perl.org/functions/close.html][black][b]close[/b][/black][/url] FILE[red];[/red]

And yes, I intentionally meant to do print sprintf. I hate printf.

- Miller
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top