⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 core.c

📁 AVR source code for performing speech, the speech voice will be like a robot voice. sources are in c
💻 C
📖 第 1 页 / 共 2 页
字号:
	#ifdef _AVR_PWM_
	TCCR1A &= ~(BV(COM1B1));	// Disable PWM
	DDRB &= ~(BV(PB2));			// make B2 an input pin
	#endif

	#ifdef _AVR_BINARY_
	SOUND_DDR &= ~(SOUND_BIT);	// Set speaker port as input
	#endif

	#ifdef _AVR_QUAD_
	QUAD_DDR &= ~(QUAD_MASK);	// Set ports as input
	#endif
#endif
}

void soundOn(void){
#ifdef _AVR_

	#ifdef _AVR_PWM_
	DDRB |= BV(PB2);			// make B2 an output pin
	TCCR1A = 0;					// disable PWM
	ICR1 = PWM_TOP;
	TCCR1B = PWM_FLAGS;
	TCNT1=0;
	TCCR1A |= BV(COM1B1);		// ENABLE PWM ON B2 USING OC1B, OCR1B
	#endif
	
	#ifdef _AVR_BINARY_
	SOUND_DDR |= (SOUND_BIT);	// Set speaker port as output
	SOUND_PORT &= ~(SOUND_BIT);
	#endif
	
	#ifdef _AVR_QUAD_
	QUAD_DDR |= (QUAD_MASK);	// Set ports as output
	QUAD_PORT &= ~(QUAD_MASK);	// all off
	#endif
	
	
	// initialise random number seed
	seed0=0xecu;
	seed1=7;
	seed2=0xcfu;
#endif
}

#ifdef _AVR_PWM_
// Logarithmic scale
//static const int16_t PROGMEM Volume[8] = {0,PWM_TOP * 0.01,PWM_TOP * 0.02,PWM_TOP * 0.03,PWM_TOP * 0.06,PWM_TOP * 0.12,PWM_TOP * 0.25,PWM_TOP * 0.5};

// Linear scale
static const int16_t PROGMEM Volume[8] = {0,PWM_TOP * 0.07,PWM_TOP * 0.14,PWM_TOP * 0.21,PWM_TOP * 0.29,PWM_TOP * 0.36,PWM_TOP * 0.43,PWM_TOP * 0.5};
#endif


void sound(uint8_t b){
	b = (b & 15);

#ifdef _LOG_
	loggerc((char)(b+'0'));
#endif

#ifdef _AVR_

	#ifdef _AVR_PWM_
	// Update PWM volume 
	int16_t duty = pgm_read_word(&Volume[b>>1]);	  // get duty cycle	
	if(duty!=OCR1B){
		TCNT1=0;
		OCR1B = duty;
	}
	#endif

	#ifdef _AVR_BINARY_
	// Update Port Volume
	if(b>=8){
		SOUND_PORT |= SOUND_BIT;
	}else{
		SOUND_PORT &= ~(SOUND_BIT);
	}
	#endif

	#ifdef _AVR_QUAD_
	b <<= QUAD_BIT;
	b &= QUAD_MASK;
	QUAD_PORT = (QUAD_PORT & ~(QUAD_MASK)) | b;
	#endif

#endif

}



uint8_t playTone(uint8_t soundNum,uint8_t soundPos,char pitch1, char pitch2, uint8_t count, uint8_t volume){
	const uint8_t* soundData = &SoundData[soundNum * 0x40];
	while(count-- > 0 ){
		uint8_t s;
		
		s = pgm_read_byte(&soundData[soundPos & 0x3fu]);
		sound((uint8_t)(s & volume));
		pause(pitch1);
		sound((uint8_t)((s>>4) & volume));
		pause(pitch2);

		soundPos++;
	}
	return soundPos & 0x3fu;
}

void play(uint8_t duration, uint8_t soundNumber){
	while(duration-- != 0){
		playTone(soundNumber,random(), 7,7, 10, 15);
	}
}


void setPitch(uint8_t pitch){
	default_pitch = pitch;
}


/*
*  Speak a string of phonemes
*/
void speak(const char* textp){
	uint8_t 
		phonemeIn,				// offset into text
		byte2,
		modifierIn,				// offset into stuff in modifier
		punctuationPitchDelta;	// change in pitch due to fullstop or question mark
	char byte1;
	char phoneme;
	const SOUND_INDEX* soundIndex;
	uint8_t sound1Num;			// Sound data for the current phoneme
	uint8_t sound2Num;			// Sound data for the next phoneme
	uint8_t sound2Stop;			// Where the second sound should stop
	char pitch1;			// pitch for the first sound
	char pitch2;			// pitch for the second sound
	short i;
	uint8_t sound1Duration;		// the duration for sound 1
	
	if(phonemesToData(textp,s_phonemes)){
		// phonemes has list of sound bytes
#ifdef _LOG_
		loggerP(PSTR("Data:"));
		logger(phonemes);
		loggerCRLF();
#endif

		soundOn();
		
		// _630C
		byte1=0;
		punctuationPitchDelta=0;

		//Q19
		for(phonemeIn=0,modifierIn=0;phonemes[phonemeIn]!=0; phonemeIn+=2, modifierIn+=2){
			uint8_t	duration;	// duration from text line
			uint8_t SoundPos;	// offset into sound data
			uint8_t fadeSpeed=0;

			phoneme=phonemes[phonemeIn];
			if(phoneme=='z'){
				delay(15);
				continue;
			}else if(phoneme=='#'){
				continue;
			}else{

				// Collect info on sound 1
				soundIndex = &SoundIndex[phoneme - 'A'];
				sound1Num = pgm_read_byte(&soundIndex->SoundNumber);
				byte1 = pgm_read_byte(&soundIndex->byte1);
				byte2 = pgm_read_byte(&soundIndex->byte2);

				duration = phonemes[phonemeIn+1] - '0';	// Get duration from the input line
				if(duration!=1){
					duration<<=1;
				}
				duration += 6;							// scaled duration from the input line (at least 6)

				sound2Stop = 0x40>>1;


				pitch1 = modifier[modifierIn];
				if(modifier[modifierIn + 1]==0 || pitch1==-1){
					pitch1 = 10;
					duration -= 6;
				}else if(modifier[modifierIn + 1]=='0' || duration==6){
					duration -= 6;
				}
				

				//q8
				pitch2 = modifier[modifierIn+2];
				if(modifier[modifierIn + 3]==0 || pitch2 == -1){
					pitch2 = 10;
				}

				//q10

				if(byte1<0){
					sound1Num = 0;
					random();
					sound2Stop=(0x40>>1)+2;


				}else{
					// is positive
					if(byte1==2){
						// 64A4
						// Make a white noise sound !
						uint8_t volume;					// volume mask
#ifdef _LOG_
						loggerP(PSTR("\nA *******"));
						logger_uint8(duration);
						loggerCRLF();
#endif
						volume = (duration==6) ? 15 : 1;  /// volume mask
						for(duration <<= 2; duration>0; duration--){
							playTone(sound1Num,random(),8,12,11, volume);
							// Increase the volume
							if(++volume==16){
								volume = 15;	// full volume from now on
							}

						}
						continue;

					}else{
						//q11
						if(byte1 != 0){
							delay(25);
						}
					}
				}

			}


			// 6186
			pitch1 += default_pitch + punctuationPitchDelta;
			if(pitch1<1){
				pitch1=1;
			}

			pitch2 += default_pitch + punctuationPitchDelta;
			if(pitch2<1){
				pitch2=1;
			}

			// get next phoneme
			phoneme=phonemes[phonemeIn + 2];

			if(phoneme==0 || phoneme=='z'){
				if(duration==1){
					delay(60);
				}
				phoneme='a';	// change to a pause
			}else{
				// s6
				if(byte2 != 1){
					byte2 = (byte2 + pgm_read_byte(&SoundIndex[phoneme-'A'].byte2))>>1;
				}

				if(byte1 < 0 || pgm_read_byte(&SoundIndex[phoneme-'A'].byte1) != 0){
					phoneme ='a'; // change to a pause
				}
			}

			// S10
			sound2Num = pgm_read_byte(&SoundIndex[phoneme-'A'].SoundNumber);

			sound1Duration = 0x80;			// play half of sound 1
			if(sound2Num==sound1Num){
				byte2 = duration;
			}

			// S11
			if( (byte2>>1) == 0 ){
				sound1Duration = 0xff;				// play all of sound 1
			}else{
				// The fade speed between the two sounds
				fadeSpeed = (sound1Duration + (byte2>>1))/byte2;

				if(duration==1){
					sound2Stop = 0x40;	// dont play sound2
					sound1Duration = 0xff;			// play all of sound 1
					pitch1 = 12;
				}
			}

			SoundPos = 0;
			do{
				uint8_t sound1Stop = (sound1Duration>>2) & 0x3fu;
				uint8_t sound1End = min(sound1Stop , sound2Stop);

				if( sound1Stop != 0 ){
					
#ifdef _LOG_
					loggerP(PSTR("\nB Remaining="));
					logger_uint8(duration);
					loggerP(PSTR("Repeat min("));
					logger_uint8(sound1Stop);
					loggerP(PSTR(","));
					logger_uint8(sound2Stop);
					loggerP(PSTR(") times,Sound#="));
					loggerc((char)(sound1Num+'A'));
					loggerP(PSTR("["));
					logger_uint8(SoundPos);
					loggerP(PSTR("]\n"));
#endif
					SoundPos = playTone(sound1Num,SoundPos,pitch1,pitch1, sound1End, 15);
				}

				// s18
				if(sound2Stop != 0x40){
#ifdef _LOG_
					loggerP(PSTR("\nC Remaining="));
					logger_uint8(duration);
					loggerP(PSTR("Repeat "));
					logger_uint8((uint8_t)(sound2Stop-sound1End));
					loggerP(PSTR(" times,Sound#="));
					loggerc((char)(sound2Num+'A'));
					loggerP(PSTR("["));
					logger_uint8(SoundPos);
					loggerP(PSTR("]\n"));
#endif

					SoundPos = playTone(sound2Num,SoundPos,pitch2,pitch2, (uint8_t)(sound2Stop - sound1End), 15);
				}

				//s23
				if(sound1Duration!=0xff && duration<byte2){
					// Fade sound1 out
					sound1Duration -= fadeSpeed;
					if( sound1Duration >= (uint8_t)0xC8){
						sound1Duration=0;	// stop playing sound 1
					}
				}


				// Call any additional sound
				if(byte1==-1){
					play(3,30);	// make an 'f' sound
				}else if(byte1==-2){
					play(3,29);	// make an 's' sound
				}else if(byte1==-3){
					play(3,33);	// make a 'th' sound
				}else if(byte1==-4){
					play(3,27);	// make a 'sh' sound
				}

			}while(--duration!=0);
		 

			// Scan ahead to find a '.' or a '?' as this will change the pitch
			punctuationPitchDelta=0;
			for(i=6; i>0; i--){
				char next = phonemes[phonemeIn + (i * 2)];
				if(next=='i'){
					// found a full stop
					punctuationPitchDelta = 6 - i; // Lower the pitch
				}else if(next=='h'){
					// found a question mark
					punctuationPitchDelta = i - 6; // Raise the pitch
				}
			}

			if(byte1 == 1){
				delay(25);
			}


		} // next phoneme

	}
	soundOff();
}

/*
*   Speak an English command line of text
*/
void say(const char * original){
	int i;
	if(textToPhonemes(original,s_vocab, phonemes)){
#ifdef _LOG_
		loggerP(PSTR("Say:'"));
		logger(original);
		loggerP(PSTR("' => Phonemes:'"));
		logger(phonemes);
		loggerCRLF();
#endif
		// copy string from phonemes to text 
		for(i = 0;phonemes[i]!=0;i++){
			g_text[i]=phonemes[i];
		}
		while(i<sizeof(g_text)){
			g_text[i++]=0;
		}

		speak(g_text);
	}
}





void init(void){
#ifdef _AVR_
	uartInit();  // initialize the UART (serial port)
	uartSetBaudRate(19200);// set the baud rate of the UART for our debug/reporting output
	rprintfInit(uartSendByte);// initialize rprintf system

	// Power save
	PRR = BV(PRTWI)	// turn off TWI
		| BV(PRSPI)	// turn off SPI
		| BV(PRADC) // turn off ADC
		| BV(PRTIM0) // turn off TIMER0
		| BV(PRTIM2) // turn off TIMER2
		;
#endif
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -