Your lowpass filter must not be loaded down with a 1k pot. It must feed an impedance of at least 16k.Gordz said:I tried a few times before to get this BTc of Roman's to work and could not get the quality I hoped for. The .wav files he had on his origional page sounded very good, nothing at all like I managed to get.
audioguru said:Why is your original sound just very distorted boomy bass,
Sound wave volume
It is critically important that the sound wave be the largest volume possible. Ideally most of the sound wave should be "peak to peak" even with some mild clipping of peaks. Many sound files (like those supplied with Windows) are very low in volume and will not encode very well.
You can download freeware wave editing software from the internet, and most of these programs will let you change formats and increase the volume of the sound. Sometimes they call this "normalising" or "maximising".
Dynamic compression
Dynamic compression refers to the dynamic range of the sound, ie, the difference in volume between the loud bits and the quiet bits. The BEST encoding result will be on sounds that have a "compressed" dynamic range, where the entire sound is loud. Think "radio advertising" for a typical example of sound of this type.
If your wave editor does not support dynamic compression you can get a result almost as good by increasing the volume until most of the peaks start to clip. Save a number of waves with different volume increases, and see which sound the best after encoding.
Perhaps because my LRC playback circuit is bad.and why is the output from the PIC just bass-less sizzling highs?
Black said:If you have an avaliable opamp in your design, you can configure it as a active low pass filter by using a cap to couple high frequencies from the output back to the inverting input. Do a web search for "opamp low pass filter".
Not sure how to respond to this. The input to the PIC is a bitstream stored in the EEPROM. Since it is a digital device I am not sure what overloading it would mean. Maybe more like the bitstream output by the PIC overloads the RC circuit?Then maybe the input to the PIC is overloaded?
I've found that BTc32 compression generates less noisy waveforms. However, I think that additional (hardware) filtering is necessary.3v0 said:I used the BTC16 encoding. I would be quite happy with the sound if I could get rid of the noise. The "Testing one two three" clip used about 0x1F00 on the EEPROM. Could be done in a bit less.
Yes.... the MAX291 is Butterworth, Here's the datasheet. I'd like to try diffrent solutions, but it probably won't be until after Christmas Holidays as I'll be away next week.audioguru said:The MAX292 is Bessel, not Butterworth but since it is an 8th order then it is still sharp enough.
Gordz said:I tried a few times before to get this BTc of Roman's to work and could not get the quality I hoped for. The .wav files he had on his origional page sounded very good, nothing at all like I managed to get. If you get this going please post your findings. There is similar stuff here :- h??p://mondo-technology.com/ under Talking Frog Box.
Procedure
Collect the speech sounds in a set of WAV or other files you can edit.
Maximize the level in the file.
Filter the file with a 3500hz low pass function.
Resample the rate to 8khz.
Cut out individual words.
Store them to disk in the SND format, 8 bits, unsigned, 8000 samples/second.
Construct a Sound Control File (filename.scf)
Use FTALK to convert the several SND files into one BIN file.
Use HEX (if necessary) to convert the BIN file to a HEX file.
eng1 said:3v0, I would be interested in seeing the routine you use to decode the bitstream. Thanks.
eng1 said:Few lines of pseudo-code will be fine, I'm going to write my own code later (C or assembly, I haven't decided yet).
I'm going to use a TIMER to send bits out (with a sampling rate of 22050 Hz, each bit will be sent on PORTx every 45.4 us). Bits are stored into 8 bit values, the most significant bit goes out first, is that correct? If that is the case I'll use a 'rlf' instruction to 'serialize' data.
// Delays are clock dependant so we will define them here
#define LONG_DELAY Delay1TCY();Delay1TCY();Delay1TCY()
// Delay10TCYx(1)
#define SHORT_DELAY Delay1TCY();Delay1TCY()
#define return(c) if(c==0)return(c);while(1)
.............................................................
// modifed for 16 bit address
void sequential_read( int addr )
{
SWStartI2C();
var = SWPutcI2C( 0xA0 ); // control byte
SWAckI2C();
var = SWPutcI2C( 0x00 ); // address to read from hi byte
SWAckI2C();
var = SWPutcI2C( addr ); // address to read from lo byte
SWAckI2C();
SWRestartI2C();
var = SWPutcI2C( 0xA1 );
SWAckI2C();
SWGetsI2C_speaker( 0x1F00); // fixed lenght for now
SWStopI2C();
}
....................................................
/************************************************************
* Function Name: void SWGetsI2C_speaker(unsigned int length )
*
* Return Value: return with error condition
* Parameters: address of read string storage location and
* length of string bytes to read
* Description: This routine reads a string from the I2C bus.
********************************************************************/
void SWGetsI2C_speaker(unsigned int length )
{
T0CONbits.TMR0ON = 0; // timer 0 off
INTCONbits.TMR0IF = 0;
while ( length --) // stay in loop until byte count is zero
{
SWReadI2C_Speaker(); // read and send a byte to the speaker
if ( !length ) // initiate NOT ACK
{
CLOCK_LOW; // make clock pin output to drive low
DATA_HI; // release data line to float high
LONG_DELAY; // user may need to modify based on Fosc
CLOCK_HI; // release clock line to float high
LONG_DELAY; // user may need to modify based on Fosc
}
else // else initiate ACK condition
{
CLOCK_LOW; // make clock pin output to drive low
DATA_LAT = 0; // set data pin latch to 0
DATA_LOW; // make data pin output to drive low
LONG_DELAY; // user may need to modify based on Fosc
CLOCK_HI; // release clock line to float high
LONG_DELAY; // user may need to modify based on Fosc
}
}
T0CONbits.TMR0ON = 0; // timer 0 off
return( 0 ); // return with no error
}
...........................................................................................
// #define SEE_BITRATE // if defined generate a signal that is 1/2 the bitrate
// EEPROM data is ignored
// you can check the birate with a freq counter
// #define SEE_BYTE // collect bits into bytes so you to check EEPROM read
#define TEST_TIME // comment out for production code
#include <p18cxxx.h>
#include <delays.h>
#include "sw_i2c.h"
/********************************************************************
* Function Name: unsigned int SWReadI2C_Speaker(void) *
* Return Value: none *
* Parameters: void *
* Description: Read 8 bits from I2C EEPROM send to speaker *
* using bit bang *
********************************************************************/
//#pragma inline
void SWReadI2C_Speaker( void )
{
unsigned char bitCnt, prevBit, curBit;
// the next two are for debugging only
unsigned char flip; // used to generate a signal to check freq
unsigned char readByte; // value of last read byte
SCLK_LAT = 0; // set clock pin latch to 0
T0CONbits.TMR0ON = 1; // timer 0 on
flip = 0;
readByte = 0;
bitCnt = 8; // set bit count for byte
do
{
#ifdef SEE_BYTE
readByte = readByte <<1;
#endif
// clock in the bit
CLOCK_LOW; // set clock pin output to drive low
DATA_HI; // release data line to float high
LONG_DELAY; // user may need to modify based on Fosc
CLOCK_HI; // release clock line to float high
SHORT_DELAY; // user may need to modify based on Fosc
while( !SCLK_PIN ) // test for clock low
{
if ( Clock_test() ) // clock wait routine
{
#ifdef TEST_TIME
while(1); // hang here, ***set breakpoint here***
#else
return; /// need error recovery here, maybe skip to next byte??
#endif
}
}
// get the bit
curBit = ( DATA_PIN );
#ifdef TEST_TIME
if( INTCONbits.TMR0IF)
while(1); // for testing hang here if we late, ***set breakpoint here***
#endif
// wait for timer to expire, for speakers bit time to start
while(!INTCONbits.TMR0IF);
// new speaker bit time starts here
INTCONbits.TMR0IF = 0; // clear timeout flag
TMR0L = 0x45; // setup timer for bit time, this is for 32Mhz 18F1330
#ifdef SEE_BITRATE
SPEAKER0 = flip; // _ _ _
flip = !flip; // change output state _| |_| |_| |_ ... test freq only
#else
SPEAKER0 = curBit;
SPEAKER1 = prevBit;
TRIS_SPEAKER1 = (curBit != prevBit); // make 2nd bit (prev) output only if not same as current
#endif
#ifdef SEE_BYTE
readByte += DATA_PIN;
#endif
prevBit = curBit;
} while ( --bitCnt ); // stay until 8 bits have been acquired
}
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?
We use cookies and similar technologies for the following purposes:
Do you accept cookies and these technologies?