Re: [hatari-devel] sound bug |
[ Thread Index |
Date Index
| More lists.tuxfamily.org/hatari-devel Archives
]
----- Douglas Little wrote:
> Hi
>
> Ok if those patches relate to known issues in sample replay, it would
> definitely be worth testing them. Or even if they relate to known issues in
> sample recording which likely apply to sample replay it would still be
> worth testing that.
>
> Unfortunately I can only test replay, not recording.
>
> D.
>
Hi,
Please give me a few pointers on reproducing the problem.
I am new to the Falcon.
- which TOS version
- which Hatari Falcon settings.
- which software.
I may be able to test the microphone also.
You can try this minimally tested patch with what you are doing to
see what how well it works. If the patch works as good as no patch,
I would consider this as progress toward the solution.
(this is the same patch as before, but compatible with recent chages)
Sincerely,
David Savinkoff
--- hatari/src/falcon/crossbar.c 2014-06-24 12:18:31.000000000 -0700
+++ hatari/src/falcon/crossbar.c 2014-06-24 15:20:00.551580338 -0700
@@ -135,6 +135,10 @@
/* ADC functions */
static void Crossbar_Process_ADCXmit_Transfer(void);
+/* Anti-alias crossbar generated samples */
+static Sint16 Crossbar_LowPassFilterLeft(Sint16 in);
+static Sint16 Crossbar_LowPassFilterRight(Sint16 in);
+
/* external data used by the MFP */
Uint16 nCbar_DmaSoundControl;
@@ -261,13 +265,12 @@
Uint32 dmaRecord_CurrentFrameStart; /* current DmaPlay Frame end ($ff890f $ff8911 $ff8913) */
Uint32 dmaRecord_CurrentFrameCount; /* current DmaRecord Frame start ($ff8903 $ff8905 $ff8907) */
Uint32 dmaRecord_CurrentFrameEnd; /* current DmaRecord Frame end ($ff890f $ff8911 $ff8913) */
- Uint32 adc2dac_readBufferPosition; /* read position for direct adc->dac transfer */
- Sint64 adc2dac_readBufferPosition_float; /* float value of read position for direct adc->dac transfer index */
Uint32 save_special_transfer; /* Used in a special undocumented transfer mode (dsp sent is not in handshake mode and dsp receive is in handshake mode) */
};
struct codec_s {
+ int FIFO_NbBytes;
Sint16 buffer_left[DACBUFFER_SIZE];
Sint16 buffer_right[DACBUFFER_SIZE];
Sint64 readPosition_float;
@@ -293,6 +296,7 @@
static struct dma_s dmaRecord;
static struct codec_s dac;
static struct codec_s adc;
+static struct codec_s mic;
static struct dsp_s dspXmit;
static struct dsp_s dspReceive;
@@ -326,6 +330,7 @@
dac.readPosition_float = 0;
dac.readPosition = 0;
dac.writePosition = 0;
+ dac.FIFO_NbBytes = 0;
/* ADC inits */
memset(adc.buffer_left, 0, sizeof(adc.buffer_left));
@@ -333,6 +338,14 @@
adc.readPosition_float = 0;
adc.readPosition = 0;
adc.writePosition = 0;
+ adc.FIFO_NbBytes = 0;
+
+ /* Microphone inits */
+ memset(mic.buffer_left, 0, sizeof(mic.buffer_left));
+ memset(mic.buffer_right, 0, sizeof(mic.buffer_right));
+ mic.readPosition = 0;
+ mic.writePosition = 0;
+ mic.FIFO_NbBytes = 0;
/* DSP inits */
dspXmit.wordCount = 0;
@@ -363,8 +376,6 @@
crossbar.gainSettingRight = 3276;
crossbar.attenuationSettingLeft = 65535;
crossbar.attenuationSettingRight = 65535;
- crossbar.adc2dac_readBufferPosition = 0;
- crossbar.adc2dac_readBufferPosition_float = 0;
/* Start 25 Mhz and 32 Mhz Clocks */
Crossbar_Recalculate_Clocks_Cycles();
@@ -1699,14 +1710,34 @@
idxPos = 0;
for (i = 0; i < size; i++) {
- adc.writePosition = (adc.writePosition + 1) % DACBUFFER_SIZE;
-
adc.buffer_left[adc.writePosition] = micro_bufferL[bufferIndex];
adc.buffer_right[adc.writePosition] = micro_bufferR[bufferIndex];
idxPos += crossbar.frequence_ratio2;
bufferIndex += idxPos>>32;
idxPos &= 0xffffffff; /* only keep the fractional part */
+
+ adc.writePosition = (adc.writePosition + 1) % DACBUFFER_SIZE;
+
+ if (++adc.FIFO_NbBytes > DACBUFFER_SIZE) {
+ adc.FIFO_NbBytes = DACBUFFER_SIZE;
+ adc.readPosition = adc.writePosition;
+ }
+ }
+
+ bufferIndex = 0;
+ for (i = 0; i < microBuffer_size; i++) {
+ mic.buffer_left[mic.writePosition] = micro_bufferL[bufferIndex];
+ mic.buffer_right[mic.writePosition] = micro_bufferR[bufferIndex];
+
+ bufferIndex++;
+
+ mic.writePosition = (mic.writePosition + 1) % DACBUFFER_SIZE;
+
+ if (++mic.FIFO_NbBytes > DACBUFFER_SIZE) {
+ mic.FIFO_NbBytes = DACBUFFER_SIZE;
+ mic.readPosition = mic.writePosition;
+ }
}
}
@@ -1728,10 +1759,16 @@
}
else {
sample = adc.buffer_right[adc.readPosition];
- adc.readPosition = (adc.readPosition + 1) % DACBUFFER_SIZE;
frame = 0;
+
+ if (--adc.FIFO_NbBytes < 0) {
+ adc.FIFO_NbBytes = 0;
+ }
+ else {
+ adc.readPosition = (adc.readPosition + 1) % DACBUFFER_SIZE;
+ }
}
-
+
/* Send sample to DSP receive ? */
if (adc.isConnectedToDsp) {
Crossbar_SendDataToDspReceive(sample, frame);
@@ -1770,6 +1807,11 @@
/* Right channel */
dac.buffer_right[dac.writePosition] = value;
dac.writePosition = (dac.writePosition + 1) % (DACBUFFER_SIZE);
+
+ if (++dac.FIFO_NbBytes > DACBUFFER_SIZE) {
+ dac.FIFO_NbBytes = DACBUFFER_SIZE;
+ dac.readPosition = dac.writePosition;
+ }
}
}
@@ -1780,45 +1822,37 @@
*/
void Crossbar_GenerateSamples(int nMixBufIdx, int nSamplesToGenerate)
{
- int i, j, nBufIdx;
- int n;
+ int i, nBufIdx;
+ unsigned n;
Sint16 adc_leftData, adc_rightData, dac_LeftData, dac_RightData;
- if (crossbar.isDacMuted) {
- /* Output sound = 0 */
- for (i = 0; i < nSamplesToGenerate; i++) {
- nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
- MixBuffer[nBufIdx][0] = 0;
- MixBuffer[nBufIdx][1] = 0;
- }
-
- /* Counters are refreshed for when DAC becomes unmuted */
- dac.readPosition = dac.writePosition;
- crossbar.adc2dac_readBufferPosition = adc.writePosition;
- return;
- }
-
for (i = 0; i < nSamplesToGenerate; i++)
{
nBufIdx = (nMixBufIdx + i) % MIXBUFFER_SIZE;
+ if (dac.FIFO_NbBytes > 0)
+ dac.FIFO_NbBytes--;
+
+ if (mic.FIFO_NbBytes > 0)
+ mic.FIFO_NbBytes--;
+
/* ADC mixing (PSG sound or microphone sound for left and right channels) */
switch (crossbar.codecAdcInput) {
case 0:
default: /* Just here to remove compiler's warnings */
/* Microphone sound for left and right channels */
- adc_leftData = adc.buffer_left[crossbar.adc2dac_readBufferPosition];
- adc_rightData = adc.buffer_right[crossbar.adc2dac_readBufferPosition];
+ adc_leftData = mic.buffer_left[mic.readPosition];
+ adc_rightData = mic.buffer_right[mic.readPosition];
break;
case 1:
/* Microphone sound for left channel, PSG sound for right channel */
- adc_leftData = adc.buffer_left[crossbar.adc2dac_readBufferPosition];
+ adc_leftData = mic.buffer_left[mic.readPosition];
adc_rightData = MixBuffer[nBufIdx][1];
break;
case 2:
/* PSG sound for left channel, microphone sound for right channel */
adc_leftData = MixBuffer[nBufIdx][0];
- adc_rightData = adc.buffer_right[crossbar.adc2dac_readBufferPosition];
+ adc_rightData = mic.buffer_right[mic.readPosition];
break;
case 3:
/* PSG sound for left and right channels */
@@ -1842,15 +1876,15 @@
break;
case 2:
/* Crossbar->DAC sound only */
- dac_LeftData = dac.buffer_left[dac.readPosition];
- dac_RightData = dac.buffer_right[dac.readPosition];
+ dac_LeftData = Crossbar_LowPassFilterLeft( dac.buffer_left[dac.readPosition] );
+ dac_RightData = Crossbar_LowPassFilterRight( dac.buffer_right[dac.readPosition] );
break;
case 3:
/* Mixing Direct ADC sound with Crossbar->DMA sound */
dac_LeftData = ((adc_leftData * crossbar.gainSettingLeft) >> 14) +
- dac.buffer_left[dac.readPosition];
+ Crossbar_LowPassFilterLeft( dac.buffer_left[dac.readPosition] );
dac_RightData = ((adc_rightData * crossbar.gainSettingRight) >> 14) +
- dac.buffer_right[dac.readPosition];
+ Crossbar_LowPassFilterRight( dac.buffer_right[dac.readPosition] );
break;
}
@@ -1859,27 +1893,59 @@
/* Upgrade dac's buffer read pointer */
dac.readPosition_float += crossbar.frequence_ratio;
- n = dac.readPosition_float >> 32; /* number of samples to skip */
-
- if (n) {
- // It becomes safe to zero old data if tail has moved
- for (j=0; j<n; j++) {
- dac.buffer_left[(dac.readPosition+j) % DACBUFFER_SIZE] = 0;
- dac.buffer_right[(dac.readPosition+j) % DACBUFFER_SIZE] = 0;
+ n = dac.readPosition_float >> 32; /* number of samples to skip */
+ for ( ; n > 1 ; n-- ) /* pull samples from FIFO */
+ {
+ if (dac.FIFO_NbBytes > 0)
+ {
+ dac.FIFO_NbBytes--;
+ dac.readPosition = ++dac.readPosition % DACBUFFER_SIZE;
}
+ Crossbar_LowPassFilterLeft( dac.buffer_left[dac.readPosition] );
+ Crossbar_LowPassFilterRight( dac.buffer_right[dac.readPosition] );
}
-
dac.readPosition = (dac.readPosition + n) % DACBUFFER_SIZE;
dac.readPosition_float &= 0xffffffff; /* only keep the fractional part */
-
- /* Upgrade adc->dac's buffer read pointer */
- crossbar.adc2dac_readBufferPosition_float += crossbar.frequence_ratio;
- n = crossbar.adc2dac_readBufferPosition_float >> 32; /* number of samples to skip */
- crossbar.adc2dac_readBufferPosition = (crossbar.adc2dac_readBufferPosition + n) % DACBUFFER_SIZE;
- crossbar.adc2dac_readBufferPosition_float &= 0xffffffff; /* only keep the fractional part */
+
+ /* Upgrade microphone buffer read pointer */
+ mic.readPosition = ++mic.readPosition % DACBUFFER_SIZE;
+
+ if (crossbar.isDacMuted) {
+ MixBuffer[nBufIdx][0] = 0;
+ MixBuffer[nBufIdx][1] = 0;
+ }
}
}
+/**
+ * LowPass Filter Left
+ */
+static Sint16 Crossbar_LowPassFilterLeft(Sint16 in)
+{
+ static Sint16 lowPassFilter[2] = { 0, 0 };
+ static Sint16 out = 0;
+
+ out = lowPassFilter[0] + (lowPassFilter[1]<<1) + in;
+ lowPassFilter[0] = lowPassFilter[1];
+ lowPassFilter[1] = in;
+
+ return out >> 2; /* Filter Gain = 4 */
+}
+
+/**
+ * LowPass Filter Right
+ */
+static Sint16 Crossbar_LowPassFilterRight(Sint16 in)
+{
+ static Sint16 lowPassFilter[2] = { 0, 0 };
+ static Sint16 out = 0;
+
+ out = lowPassFilter[0] + (lowPassFilter[1]<<1) + in;
+ lowPassFilter[0] = lowPassFilter[1];
+ lowPassFilter[1] = in;
+
+ return out >> 2; /* Filter Gain = 4 */
+}
/**
* display the Crossbar registers values (for debugger info command)