Roman's btc 1 bit sound

Thread Starter

powzoom

Joined Jan 18, 2009
41
I've been trying to get Roman's Btc 1 bit sound encoding to work with a pic but all I hear is noise. Below is my code and attached is the output of pin RA5. Please let me know if there is anything wrong. The sound sample is at 8KHz and the pic is running at 8Mhz/4=2Mhz a cycle.

const char sound_data[] =
{0xAB,0x54,0xAB,0x29,0xAD,0x52,0x55,0xB5
,0x2A,0xD5,0x29,0x5D,0xA8,0x8B,0xB6,0x92
...
...
}

#define testbit_on(data,bitno) ((data>>bitno)&0x01)

OPTION = 0b11001000; // bit 4 set means no prescale
T0IE = 1; //enable TMR0 overflow interrupts
ei(); // enable global interupts

char c_bit =7;
int i =0;
char byte = 0;

for (;;)
{

count = 0;
if(f_Play)
{
if (c_bit<=0)
{
c_bit=7;
i++;
}
if (byte = sound_data)
{
RA5 = testbit_on(byte,c_bit);
}

f_Play=0;
c_bit--;
}
}

void interrupt Timer0_ISR(void)
{
T0IF=0; //clear TMR0 flag
f_Play=1;
}
 

Attachments

THE_RB

Joined Feb 11, 2008
5,438
Gee thats hard to read without formatting. Try using the code tags nextime you post code please! :)

I cant see any obvious bugs but it's a little convoluted. You could try getting rid of the funky looking macro and maybe use something a little easier to read (and debug) like this simple 8bit loop;

Rich (BB code):
byte = sound_data;
c_bit = 8;
while(c_bit)
{
	while(!f_play);	// wait for f_play to be set
	f_play = 0;
	if(byte & 0x80) RA5 = 1;
	else            RA5 = 0;
	byte = (byte << 1);
	c_bit--;
}
i++; (etc)


But that doesn't mean there isn't a bug elsewhere in your code etc. What program generated the BTc sound data you have in sound_data[] ?? Is it formatted to play MSB first? 8kHz is very low too, even if that is playing properly it will sound pretty trashy, you might want to bump up to 15625 or 19531 etc.
 

hgmjr

Joined Jan 28, 2005
9,027
I've been trying to get Roman's Btc 1 bit sound encoding to work with a pic but all I hear is noise. Below is my code and attached is the output of pin RA5. Please let me know if there is anything wrong. The sound sample is at 8KHz and the pic is running at 8Mhz/4=2Mhz a cycle.

Rich (BB code):
const char sound_data[] =
{0xAB,0x54,0xAB,0x29,0xAD,0x52,0x55,0xB5
,0x2A,0xD5,0x29,0x5D,0xA8,0x8B,0xB6,0x92
...
...
}
 
#define testbit_on(data,bitno) ((data>>bitno)&0x01)
 
OPTION = 0b11001000; // bit 4 set means no prescale
T0IE = 1;         //enable TMR0 overflow interrupts
ei();        // enable global interupts
 
char c_bit =7;
int i =0;
char byte = 0;
 
for (;;)
{
     count = 0;
     if(f_Play)
     { 
          if (c_bit<=0)
          {
               c_bit=7;
               i++;
          }
 
          if (byte = sound_data)
          {
               RA5 = testbit_on(byte,c_bit);
          }
 
          f_Play=0;
          c_bit--;
     }
}
 
void interrupt Timer0_ISR(void)
{
     T0IF=0; //clear TMR0 flag
     f_Play=1; 
}



formatted up your code for easier viewing.

hgmjr
 

Thread Starter

powzoom

Joined Jan 18, 2009
41
Sorry about the format, didn't realize about code tags. 8kHz is slow, yea, but I'm waiting for a 20Mhz oscillator to come in the mail. For now I have just the 8Mhz internal oscillator. With the 20Mhz I could use timer0 -> 1/(20Mhz/4) *256 -> tmr0 clicks every 51us or the same as 19531Hz.

The program to convert is btc2ccs which I found on this post,
http://www.ccsinfo.com/forum/viewtopic.php?p=103428
It outputs the same numbers as the btc mikro .c format but formatted for copy and paste.

I'm pretty sure its MSB first although I tried it both ways to make sure and I get noise each time. The sound clip is just a few seconds of voice.

I've modified your code so that the chip isn't wasting cycles and can attend to other things eventually. However, the sound is still garbled and just noise.
Rich (BB code):
    char c_bit = 0;
    int i =0;
    char byte = 0;

    byte = sound_data[0];

    for (;;)
    {        
        if(f_Play)
        {            
            if (c_bit==8)
            {
                c_bit=0;
                i++;
                byte = sound_data;
            }

            if (byte & 0x80)
                RA5=1;
            else
                RA5=0;    

            byte = (byte << 1);
            f_Play=0;
            c_bit++;        
        }
    }
 

THE_RB

Joined Feb 11, 2008
5,438
Hmm, I hadn't seen that BTC2CCS.exe converter before. Thanks for the link.

Since that program converts sound from MikroC format as produced by my BTc sound encoder software, I assume you used that to generate the original BTc sound data?? How did the sound look? Was it good in amplitude, ie most of the sound swinging from top to bottom on the BTc encoder screen? 1 bit sound is critical regarding amplitude as the PCM noise is fixed amplitude and large, so you need the largest possible amplitude sound wave. That's covered in the help file that comes with the BTc encoder.

Other than that, one possible reason might be that the program you used to convert to CCS format might have swapped the MSB first of the BTc format to LSB first. Thats DOES garble the sound pretty bad. You could try changing your code
Rich (BB code):
            if (byte & 0x80)
                RA5=1;
            else
                RA5=0;    
            byte = (byte << 1);
to:
            if (byte & 0x01)
                RA5=1;
            else
                RA5=0;    
            byte = (byte >> 1);
Which is a pretty easy test.

Finally, 8kHz is never going to sound good, even with a high amplitude original sound and good encoding parameters. There will be a lot of loud noise at bitrate/2 /3 and /4, which is 4kHz, 2.6kHz and 2kHz. Right in the powerband of most speakers and the human ear. You really should change to 19531 if you can and use some pretty good low pass filtering, generally consider the RC of the BTc filter as a "modeling stage" to reproduce the basic waveform and add additonal RC filter stages to try to remove most of the PCM noise. At 8kHz it is just not gonna sound that good. :)
 

Thread Starter

powzoom

Joined Jan 18, 2009
41
Thanks for the replies. I took some time off from the project and came back today. I figured out the problem and it was something really stupid. I forgot to but 0b before a binary number that sets the oscillator speed. Funny how something so small causes the whole thing not to work right. Also funny how I figured out the problem in minutes as opposed to the hours I stared at it the other day, ha. I've also added an active filter to take out the higher frequencies. It sounds cheapish but there's no problem in hearing the voice in the recording. I'm still waiting on the 20Mhz oscillator to up the sample rate.
 
Hello,

I do not know the frequencies you are working on, but since you have an op amp, why not make a 2 pole filter?
This could let you get better sounds removing more noise.

Regarding your code, I would discourage using MACROs with the #define preprocessor directive. Macros can hide bugs. In your case I would have created a function.
Don't speed up the code before is not even working, Optimizations must be done if required.

regarding the for ( ;; ) infinite loop I would have used while (1) or even better:

#define TRUE= 0x01
...

while (TRUE)

...but these are just some code practices and habits.


Ciao,

Mauro
 

THE_RB

Joined Feb 11, 2008
5,438
while(1) uses proper C syntax and is guaranteed to compile.

for( ; ; ) just happens to compile to the same result... probably. ;)
 
Yes they do, indeed.

but:

while (1)

it's a clear way to say, I'm not changing anything in the loop which will be always passing the test.

when you read for ( ; ; ) is not as clear. Furthermore for ( ; ; ) is a powerful instruction and its translation in assembly is more complex than a while ( ), this means you can save bytes. This is a kind of Optimization which is coming indirectly and for free by a simple code style.

In c and c++ codes such as firefox and tunderbird you generally find while (1) instead of for ( ; ; ). If most of the people use something that could be done also in different ways but without advantages, follow the people.
More people will understand you with less effort.

If most of the people are doing something and you can do better, do your way but explain it.

Ciao,

Mauro
 
Top