ในกรณีของ RTTY 45.45 baud คุณจะมีสัญลักษณ์ที่ไม่ใช่จำนวนเต็มตัวอย่างดังนั้นคุณต้องใช้ฟังก์ชันที่สามารถเรียกแต่ละตัวอย่างแล้วส่งสัญญาณในค่าส่งคืนเมื่อสัญลักษณ์นั้นสิ้นสุด และคุณจำเป็นต้องมีแอคติมูเลเตอร์แบบเฟสซึ่งจะทำงานต่อเนื่องซึ่งเฟสของคลื่นไซน์นั้น
ในการส่งสัญลักษณ์ที่มีความยาวไม่ใช่จำนวนเต็มคูณอัตราตัวอย่างคุณต้องใช้ฟังก์ชันนี้ ...
int millisecondTimer(double milliseconds, double samplerate, int resettime)
{
static int fracsample=0;
static int counter=0;
static int retvalue=0;
static int first=1;
static double oldmilliseconds=1.0;
static int whole_samples=0;
static int samerror=32768;
if(resettime==1)
{
samerror=0;
counter=0;
retvalue=1;
first=1;
}
if(first==1 || milliseconds !=oldmilliseconds)
{
double samplesneeded=1;
double wholesamples=0;
samplesneeded=(samplerate) * (milliseconds /1000.0);
samerror=(modf(samplesneeded, &wholesamples)) * 32768.0;
whole_samples=wholesamples;
first=0;
}
if(counter<=whole_samples)
{
retvalue=2;
counter++;
}
else
{
counter-=whole_samples;
retvalue=1;
fracsample+=samerror;
oldmilliseconds=milliseconds;
if(fracsample>=32768)
{
fracsample-=32768;
counter--;
}
}
return retvalue;
}
หากต้องการใช้ให้สร้างตัวอย่างคลื่นไซน์ถัดไปและเรียกใช้ฟังก์ชันนี้จากนั้นตรวจสอบว่าค่าส่งคืนไม่เท่ากับสอง หากมันไม่เท่ากับสองให้เลื่อนไปที่สัญลักษณ์ถัดไปและตัดสินใจว่าคุณกำลังส่งเครื่องหมายของช่องว่างหรือไม่จากนั้นเรียกใช้ฟังก์ชันนี้อีกครั้งภายในบล็อกของรหัสซึ่งดำเนินการเมื่อคุณพบว่าค่าส่งคืนไม่เท่ากับสอง
และนี่คือตัวสะสมเฟสจากเฟิร์มแวร์ Rockbox โดยมีการเปลี่ยนแปลงเพื่ออนุญาตให้มีการเปลี่ยนแปลงแอมพลิจูด (ปริมาตรเต็มคือ 32767, 180 องศาจากเฟสเต็มโวลุ่มคือ -32768)
signed short lerpsin(float frequency,signed short amplitude,unsigned long samplerate)
{
/* 128 sixteen bit sine samples + guard point */
static unsigned long phase=0;
unsigned int pos =0;
unsigned short frac=0;
static unsigned long step=0;
static float old_frequency=0;
signed short diff=0;
static const signed short sinetab[129] =
{
0, 1607, 3211, 4807, 6392, 7961, 9511, 11038,
12539, 14009, 15446, 16845, 18204, 19519, 20787, 22004,
23169, 24278, 25329, 26318, 27244, 28105, 28897, 29621,
30272, 30851, 31356, 31785, 32137, 32412, 32609, 32727,
32767, 32727, 32609, 32412, 32137, 31785, 31356, 30851,
30272, 29621, 28897, 28105, 27244, 26318, 25329, 24278,
23169, 22004, 20787, 19519, 18204, 16845, 15446, 14009,
12539, 11038, 9511, 7961, 6392, 4807, 3211, 1607,
0, -1607, -3211, -4807, -6392, -7961, -9511, -11038,
-12539, -14009, -15446, -16845, -18204, -19519, -20787, -22004,
-23169, -24278, -25329, -26318, -27244, -28105, -28897, -29621,
-30272, -30851, -31356, -31785, -32137, -32412, -32609, -32727,
-32767, -32727, -32609, -32412, -32137, -31785, -31356, -30851,
-30272, -29621, -28897, -28105, -27244, -26318, -25329, -24278,
-23169, -22004, -20787, -19519, -18204, -16845, -15446, -14009,
-12539, -11038, -9511, -7961, -6392, -4807, -3211, -1607,
0,
};
if(frequency!=old_frequency)
{
step = 0x100000000ull*frequency / samplerate;
}
phase+=step;
pos = phase >> 25;
frac = (phase & 0x01ffffff) >> 9;
diff = sinetab[pos + 1] - sinetab[pos];
old_frequency=frequency;
return ((-((sinetab[pos] + (frac*diff >> 16)))) * amplitude) >> 15;
}