Jump to content

Adding Boot sound (sub part of How to boost the OS X boot process)


GrootWitBaas
 Share

47 posts in this topic

Recommended Posts

ok here is what I have for reading the wav file so far.

 

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void read_wav_header(unsigned int *samp_rate, unsigned int *bits_per_samp,
				 unsigned int *num_samp);
void read_wav_data(int *data, unsigned int samp_rate,
			   unsigned int bits_per_samp, unsigned int num_samp);
int conv_bit_size(unsigned int in, int bps);

int main(void)
{
printf("\n\nstart here\n");
freopen ("sosume.wav","r",stdin);
unsigned int samp_rate, bits_per_samp, num_samp;
read_wav_header(&samp_rate, &bits_per_samp, &num_samp);
printf("samp_rate=[%d] bits_per_samp=[%d] num_samp=[%d]\n",
	   samp_rate, bits_per_samp, num_samp);

int *data = (int *) malloc(num_samp * sizeof(int));
read_wav_data(data, samp_rate, bits_per_samp, num_samp);

unsigned int i;
for (i = 0; i < num_samp; ++i) {
	printf("bit %d data = %d\n",i, data[i]);
}

return EXIT_SUCCESS;
}

void read_wav_header(unsigned int *samp_rate, unsigned int *bits_per_samp,
				 unsigned int *num_samp)
{
unsigned char buf[5];
printf("in read \n");
/* ChunkID (RIFF for little-endian, RIFX for big-endian) */
fread(buf, 1, 4, stdin);
buf[4] = '\0';
if (strcmp((char*)buf, "RIFF")) exit(EXIT_FAILURE);
printf("RIFF done \n");

/* ChunkSize */
fread(buf, 1, 4, stdin);

/* Format */
fread(buf, 1, 4, stdin);
buf[4] = '\0';
if (strcmp((char*)buf, "WAVE")) exit(EXIT_FAILURE);
printf("Format done \n");


/* Subchunk1ID */
fread(buf, 1, 4, stdin);
buf[4] = '\0';
if (strcmp((char*)buf, "fmt ")) exit(EXIT_FAILURE);

/* Subchunk1Size (16 for PCM) */
fread(buf, 1, 4, stdin);
if (buf[0] != 16 || buf[1] || buf[2] || buf[3]) exit(EXIT_FAILURE);
printf("16 or pcm done \n");


/* AudioFormat (PCM = 1, other values indicate compression) */
fread(buf, 1, 2, stdin);
if (buf[0] != 1 || buf[1]) exit(EXIT_FAILURE);
printf("Audio Format done \n");

/* NumChannels (Mono = 1, Stereo = 2, etc) */
fread(buf, 1, 2, stdin);
unsigned int num_ch = buf[0] + (buf[1] << 8);
if (num_ch != 1) exit(EXIT_FAILURE);
printf("Num Chn done \n");

/* SampleRate (8000, 44100, etc) */
fread(buf, 1, 4, stdin);
*samp_rate = buf[0] + (buf[1] << 8) +
(buf[2] << 16) + (buf[3] << 24);
printf("Sample rate done");

/* ByteRate (SampleRate * NumChannels * BitsPerSample / 8) */
fread(buf, 1, 4, stdin);
const unsigned int byte_rate = buf[0] + (buf[1] << 8) +
(buf[2] << 16) + (buf[3] << 24);
printf("Byte rate done\n");

/* BlockAlign (NumChannels * BitsPerSample / 8) */
fread(buf, 1, 2, stdin);
const unsigned int block_align = buf[0] + (buf[1] << 8);
printf("Block align done");

/* BitsPerSample */
fread(buf, 1, 2, stdin);
*bits_per_samp = buf[0] + (buf[1] << 8);

if (byte_rate != ((*samp_rate * num_ch * *bits_per_samp) >> 3))
	exit(EXIT_FAILURE);

if (block_align != ((num_ch * *bits_per_samp) >> 3))
	exit(EXIT_FAILURE);
printf("Bits per sample done\n");


/* Subchunk2ID */
fread(buf, 1, 4, stdin);
buf[4] = '\0';
if (strcmp((char*)buf, "data")) exit(EXIT_FAILURE);
printf("Subchunk done\n");

/* Subchunk2Size (NumSamples * NumChannels * BitsPerSample / 8) */
fread(buf, 1, 4, stdin);
const unsigned int subchunk2_size = buf[0] + (buf[1] << 8) +
(buf[2] << 16) + (buf[3] << 24);
*num_samp = (subchunk2_size << 3) / (
									 num_ch * *bits_per_samp);
printf("sub2 done \n\n\n");
}


void read_wav_data(int *data, unsigned int samp_rate,
			   unsigned int bits_per_samp, unsigned int num_samp)
{
printf("start read data\n\n");
unsigned char buf;
unsigned int i, j;
for (i=0; i < num_samp; ++i) {
	unsigned int tmp = 0;
	for (j=0; j != bits_per_samp; j+=8) {
		fread(&buf, 1, 1, stdin);
		tmp += buf << j;
	}
	data[i] = conv_bit_size(tmp, bits_per_samp);
}
}


int conv_bit_size(unsigned int in, int bps)
{
printf("conv bit size invoked \n");
const unsigned int max = (1 << (bps-1)) - 1;
return in > max ? in - (max<<1) : in;
}

 

This need to have also sosume.wav (with 1 chanel audio) in the same folder

 

The problem is I see a lot of Negative numbers ....not what I was expecting. the printf's are mostly for debug

 

Maybe some one have a idea on this

 

PS it is a lot of code, but can be cleaned up easy, just had to get it to work, and yes it is not ideal to open the file to stdin ...but I don't know better right now .... ;)

 

I have also code for playing wav files, but not to SPKR, to sound card, using lots of includes ....I want to avoid that

Link to comment
Share on other sites

Reference the "old" speaker.h to play fixed frequencies (as opposed to WAV).

Been reading the Intel 8254 datasheet and found another bug in my original code that seems to be also in GWB's melody version above. Sending the wrong value to port 43 when setting up the timers:

I think should be:

	__asm__ volatile("movb 0xb6, %%al		\n\t"	/* prepare timer to start generating sound */

and not 4b. No idea where I got that from! Amazing it even worked...

 

Pondering about the playing out PCM, whether to go the route of using Counter0 to generate a stable "timebase" or perhaps easier to just use a "wait/pause" between sending next value. But I guess that second approach means people would have to tune for their own hardware....But you guys may be ahead of me here!

Link to comment
Share on other sites

It worked because one was Binary Code Decimal(0x4b=01001011) and the other binary(0xB6=10110110).

See this page

 

A wait pause is the best way from what I can see, we have less than 3 seconds of audio, sampled at a very high rate (lots of data) but we can only use 8 bit at 22khz in reality if we use the pc speaker.

Link to comment
Share on other sites

It worked because one was Binary Code Decimal(0x4b=01001011) and the other binary(0xB6=10110110).

Hm, thought the BCD flag only applied to the counter (input data and countdown) format. Rather than the format of this config data. If so, I guess it worked as whilst 4Bh means talking about Timer1..oops, but just happened that timer 2 might have been set by BIOS to squarewave mode already. Anyway, I figure to stick with B6 'coz I (now) understand that approach!

Link to comment
Share on other sites

Hi GWB,

Since I've no idea how to read in data file (not really understanding the example you posted above!), I thought I'd focus on some lower level stuff.

 

The enclosed files have a foundation for an attempt at doing a PWM type approach to generate the voltage level for each PCM data byte. Slightly different from that example from games.com. Might not work out, but I wanted to re-invent the wheel now that I understand the principles!

 

Main thing is I don't yet have any mechanism for getting the data bytes into the routines. Just have hardcoded single data item for now as a placeholder.

 

Am still thinking it might be OK to load the raw PCM data into the bootloader like is done for DSDT or DP injection etc, at least for now. Or even pre-modified data, to prevent need for doing any math on the data. The data is never going to change. Of course, a general purpose ability to sound any suitable WAV file is nice, but also beyond the purpose to generate a boot chime ;)

 

Files do compile, but is surely totally nasty coding breaking all best practices.

 

speaker_pwm_c.txt

speaker_pwm_h.txt

 

EDIT: Don't think this is gonna be OK, since I see the 22lHz WAV file is 2 bytes, 16 bits per sample. But that's easy to handle with minor changes.

Link to comment
Share on other sites

I have sosume.wav "decoded" in 8bit. The stream, comma separated is in the file below. sosume_c.txt

 

I will have a look at your files shortly, but from a quick glance it looks like it will work with my data stream.

 

Hint: unsingned int data[38440] = {data1,data2 ....,data 38440};

Link to comment
Share on other sites

I have sosume.wav "decoded" in 8bit. The stream, comma separated is in the file below.

Aha.....great minds think alike! After posting above, I grabbed Audacity and also created 22kHz and 16kHz 8 bit stuff. Sounds a bit nasty (noisy), so ideally 16bit is way to go. But for now I think 8 bit is easier to handle.

Although 16 I guess has negative values (2's compliment?) which is probably not good for us unless more maths done on the data to shift the levels..

Link to comment
Share on other sites

8 bit sounds ok if you take the fact that the best a pc speaker will ever do is 8bit. It is just not possible to sample more. I can extract the 16 bit and shift it, but I believe we should stick with 8. will have time to look at your code in about 30 min ...sure we will get a nice sound later today, or at least something. I have currently a do re me fa so la ti do and back twice boot tone :thumbsup_anim:

Link to comment
Share on other sites

Once the sound is flowing, then consider using LZSS encoding because the boot loader includes support for LZSS decoding :censored2:

 

tell me how ....wait I'll use google :(

 

now maybe DHP(or any one else) can tell me why do I get implicit declaration of function ‘clock’

when trying to add this. From what I have seen clock Should be standard

#include "speaker.h"
#include "sosume.c"
#include <time.h>
#include <sys/time.h> 

#ifndef CLOCKS_PER_SEC
#define CLOCKS_PER_SEC CLK_TCK
#endif // CLOCKS_PER_SEC 

void localwait ( int waittime )
{
clock_t endwait;
endwait = clock() + waittime * (CLOCKS_PER_SEC / 22050);
while (clock () < endwait) {}
}

Link to comment
Share on other sites

now maybe DHP(or any one else) can tell me why do I get implicit declaration of function ‘clock’

when trying to add this. From what I have seen clock Should be standard

It isn't. Don't forget that you are working in a boot loader. Try function time18() in biosnfs.c

Link to comment
Share on other sites

So, got sound working from a data file array [] thingy. Well, noise actually, not music - yet. LOL.

 

Missed an $ on the hex value sent to control port on %%43 in speaker.h. You'll know that if all you get is ~1kHz tone!

Also the line to calculate delay value in speaker.c (with 0.5 in it) causes boot crash.

So messing with alternate solutions there to work out and apply the right delay.

 

As for getting noise not sound, I have ideas to investigate:

- Is speaker too slow to move?...try running at 16kHz or less*.

- My data is not the best, as 8bit with 0x7F as center ("2.5V"), so incredibly non-linear I suspect

- Loop Timings to generate quasi-PWM may just not be working right. Oh for an oscilloscope!

Perhaps will have to try the other approach...

 

*With say an 8kHz sample rate but perhaps needing 2x oversampling. Also to reduce the number of data bytes.

 

More later...

Link to comment
Share on other sites

I have a tone, either less than 100ms, or a loooooooooooooonnnnnnnnnnnnnnggggggggggggggggg apple boot tone about 10-15 seconds. I will clean up the files I have and add them here soon. I need to figure out this compression that DHP mentioned also. I have now the data extracted as Hex and pass a 0xFF as last bit to signal end. give me some minutes and I'll add what I have so far. Also DHP pointed again me in the direction about sleep/delay/clock and I will work on this also.

 

ok now I post a reply here to a post from DHP in the revo thread, but this will be self explaining .....

 

1.) Read a file/function and try to understand it.

2.) Fix indention and other style nits.

3.) Add comments.

4.) Strip the code to a bare minimum.

5.) Change it to make it faster.

6.) Remove global dependencies as much as possible.

7.) Rename function names and variables so that they tell us what they're about.

8.) Combine functions into one (reduce memory usage and to speed it up).

9.) Strip unused / unwanted function arguments.

 

And this is usually when I am starting to feel confident enough to make some really big changes. After nine iterations and days/weeks of fine-tuning. That's also how I learn something. Not by doing a simple copy / paste because the first time I run into some kind of bug, I am forced to start doing the same things anyway.

 

Thanking you young one, for teaching this old man how it should be done ....it is so true and I see it now with the boot sound side project. It is possible, it might even be easy. We might even be able to use the on-board sound, but most of all, dusting off snipets of 10-20 year old code and trying to make it work is actually more work than doing it from scratch.

 

Attached is the data it the hex dump like I have it now.

data_c.txt

Link to comment
Share on other sites

Bump..?

no bumps, but give it time, I need to learn how it all works and then we will be able to do it. I know it is possible, both from a hardware and software point of view, it is just a matter of time until we figure out how to do it.

 

I have also been busy at work so did not have a whole lot of time

Link to comment
Share on other sites

I have also been busy at work so did not have a whole lot of time

Ditto. But hoping to get back on it in the next day or two. Also hoping the "time off" has given time for my sub-conscious to work out what I'm doing wrong, so that it's obvious when I look at it again!

Link to comment
Share on other sites

  • 1 month later...

erm mostly stationary. I had other things to work on and did not have any time to work on this. It is spring now so my RC Helicopters is getting more attention than this :)

I don't know when this will be finished. Current status is I can make basic tone or tone sequence on boot.

Link to comment
Share on other sites

  • 2 weeks later...

GrootWitBaas, Please pardon me for interjecting before you've even finished this thread but I think what I have is somewhat related.

 

The above topic is of great interest to me and obviously anyone reading it as well. I am hoping GrootWitBaas's final instructions will not be beyond my ability. That being said, and while waiting for the exciting conclusion; I have a method that will play the boot chime after the splash screen but before the login window. I know it’s still not in the right place (but at least earlier than any other method I could find). However, if you are logging in automatically you are better off creating an applescript , saving it as an application and adding it to your login items in users pref pane if that’s all you want. That is easy and can be googled.

 

What my method does:

 

These instructions load all needed audio kexts during the apple splash screen. Then at the end of that and before the login window, the plist file (see below) will invoke the boot chime aiff file resulting in a playing of the sound. I would like it to play earlier but cannot find any way within the scope of my skill to make that happen. Besides, messing around with the actual bios with non manufacturers flash updates sounds a little scary

 

What you’ll need:

1. First your audio must be working. Mine uses VoodooHDA and I have not tested this with any other audio kext.

2. The attached plist file and place it in “/System/Library/LaunchDaemons”

3. Find and download “pfix”. You may already have it if your installation came with a folder in the root called “Hackintosh Tools”. If not, just Google of course.

 

Now after you have completed step 1 and 2 of the above, we need to get your audio kext(s) loaded into the “/Extra/Extensions” folder.

 

Simply go into the “/System/Library/Extensions” folder and copy your primary audio kext i.e. VoodooHDA.kext and paste it into the “/Extra/Extensions” folder.

 

Now you need to download and install the G3.aiff file and place it in “/Extra/MacChimes/” you must create the last folder.

 

You can try to run pfix now and reboot. It may work. I say “may” because if it does not, like it did not with me initially, I did the following additional copy and paste.

 

Go back to “/System/Library/Extensions” and search for any kext with the word “audio” in it several but not too many should appear. Select them all and copy and paste into “/Extra/Extensions” and run pfix again.. Now of course reboot and it should work.

 

*READ FIRST

 

You will benefit from having an almost duplicate (i.e. custom for your system) osx86 installation on a flash stick or separate partition. That way you can easily use that to access the modified folders and undo all of the above in the event you get a kp. You shouldn’t get a kp, but I always like to be careful when I goof with my system settings. Otherwise you will have to try safe mode and/or single user mode to undo changes.

 

If after doing this you would like to experiment with the plist file, download and install "lingon" the demo will work just fine.

G3.aiff

com.apple.abootchime.plist.zip

Link to comment
Share on other sites

  • 2 months later...
  • 3 weeks later...
 Share

×
×
  • Create New...