login

online now

We have 105 guests and no members online

search

 
Welcome, Guest
Username: Password: Remember me
  • Page:
  • 1

TOPIC: can't seem to set accurate frequency in Synth mode

can't seem to set accurate frequency in Synth mode 6 years 8 months ago #66

  • gslavenburg
  • gslavenburg's Avatar
I'm trying to get a 2000 Hz sinewave. My code below results in 1953 Hz. Experimenting with it a bit, it seems I can only get either 1953 Hz or 2232 Hz and nothing in between.

I added some debug code to setFreqVal in the GinSingSynth library, and it looks that registers FreqFine, Low, High (17, 18 and 19) are set with the correct values. But overriding FreqFine or FreqLow has no effect on the actual frequency.

Given the datasheet, it would seem you can get any frequency (24b frequency control).

Any suggestions welcome!

s = GS.getSynth(); // get the synth mode interface
s->begin (); // enter synth mode
s->selectBank ( BANK_A );
s->setPatch ( OSC_1_TO_MIXER );
s->setFrequency ( OSC_1 , 2000.0f);

synthamp = 1.0f; // initial amplitude guess
s->setAmplitude ( OSC_1 , synthamp );
s->setWaveform ( OSC_1 , SINE ); // start the sinewave
}
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 8 months ago #67

I have taken a look at this, I think you have found a bug in the waveform selection code.

It appears that if you explicitly set the waveform type as you do below, the overflow bit does not get set properly for sine waves. The result of not having the overflow bit set with a sine wave is that the frequency takes on quantized values as the waveform retriggers when there are still steps remaining during the cycle.

A possible workaround for now is to NOT use the setWaveform() function if you want to use a sine wave for accurate frequencies. In the code you have listed, try removing the setWaveform() call to see if it fixes the problem. We will take a look at the function call to figure out a way to make sure the overflow bit gets set properly.

For reference, the code currently looks like this:
void GinSingSynth::setWaveform  ( GSSynthOsc oscIdx , GSWaveType waveform )
{
	ubyte voiceIdx = OscIdxToVoiceIdx(oscIdx);
	

	
	// send a reset command ( required to change waveforms )
	
	reset ( oscIdx );

	
	// set the oscillator control bits ( low 3 bits )
	// overflow bit is bit 4 and is turned off only for sine
	
	ubyte waveByte;
	
	switch ( waveform )
	{
		case SINE     : waveByte = 0x80; break;
		case TRIANGLE : waveByte = 0x81; break;
		case SAWTOOTH : waveByte = 0x82; break;
		case RAMP     : waveByte = 0x83; break;
		case PULSE    : waveByte = 0x84; break;
		case NOISE    : waveByte = 0x85; break;
		case LEVEL    : waveByte = 0x86; break;
	}
	
	
	
	// write the waveform type bits (0-3)
		
	if ( voiceIdx != OSC_ALL )  
          gsPtr->sendCommand ( WriteOneByteWithMask , 
                               _ctrlRegs [ voiceIdx ] , 
                               waveByte , OC_WaveTypeCtrlBits );

	else                       
         _setAllOscReg1ByteMask  ( _ctrlRegs , waveByte , OC_WaveTypeCtrlBits );
						 

						 
}
Last Edit: 6 years 8 months ago by administrator.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 8 months ago #72

Another function that you might find useful for setting accurate frequencies is the setFreqVal() function - this takes an unsigned long where the low three bytes are used to set the frequency registers directly. The bytes are ordered as:

[freq HI][freq LO][freq FINE]
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 8 months ago #74

  • gslavenburg
  • gslavenburg's Avatar
thanks for reproducing this and finding the root cause. I will try the workaround tonight and post the result.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 8 months ago #80

  • gslavenburg
  • gslavenburg's Avatar
I confirm that removing the s->setWaveform line results in perfect 2000 Hz sinewave.

Thanks very much for the help. I'll take this out of my source code for now until the library has a permanent fix.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #82

  • gslavenburg
  • gslavenburg's Avatar
After more experimentation, the workaround causes some other issue that I don't fully understand. When putting the sound on a speaker, besides the 2.00 kHz I now hear a 'buzz/rattle' that wasn't there before.

Maybe omitting the reset leaves some control settings so that the envelope is modulated. On the scope I see some kind of very slow AM modulation with sawtooth shape and 10 Hz or so frequency.

Here is my code (workaround = 1, freq = 2000.0):
  s->begin ();                                       // enter synth mode
  s->selectBank   ( BANK_A );  
  s->setPatch     ( OSC_1_TO_MIXER ); 
  s->setFrequency ( OSC_1 , freq ); 
  synthamp = 0.2f;                                   // initial amplitude guess
  s->setAmplitude ( OSC_1 , synthamp );
  if (workaround == 0) s->setWaveform  ( OSC_1 , SINE );

Try putting it on a speaker and you will see what I mean. With workaround = 0, the frequency is 1953 Hz and sound is pure. With workaround = 1, the frequency is exact 2000 Hz, but there is a buzz/rattle.

thanks, Gerrit
Last Edit: 6 years 7 months ago by administrator.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #83

Interesting. I would not expect that behavior given that removing that single function call since just avoids setting a register value that pertains only to that specific oscillator. In other words, any modulation or other DCOs that may cause this kind of interaction should be there in either case.

I am currently not in front of a GinSing, but I will take a look to see if I can reproduce this. I wonder if it might be the amplifier IC generating some overtones; as with the software case it would seem the effect should be there in either case though. Perhaps you can tap the signal at the input pin of the audio amp to see if it looks correct there...
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #84

  • gslavenburg
  • gslavenburg's Avatar
I've put both the input and output of the LM386 on the scope to try understand what is going on. Unfortunately, I can't really 'see' it. I think the buzz/rattle like noise is 30 - 40 dB down, and although you can hear it, it is too weak for a scope to show it.

Please disregard my original observation that it is amplitude modulation - that was due to my scope sampling at a frequency close to a multiple of the GinSing sample frequency, causing artefacts. Soon as I change the timebase, it doesn't show.

Interestingly, if I use the workaround and program 1953.1 Hz at 0.2f amplitude, there is definitely an artefact there that isn't there when I remove the workaround (and output 1953.1 Hz). At that frequency the artefact isn't a rattle, but sounds almost like some tones moving in and out.

For now, I'm just going to keep working without the workaround, since I'd rather have a slight frequency error then the buzz/rattle.

Happy Thanksgiving !
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #85

Also have been fooled by sampling error - my scope is a presonus sampler which introduces stepping. So what I see is a very clean sine wave, but stepped levels. If this were the actual signal it would a lot of overtone artifacts. If I can a real scope it might be less misleading.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #86

I can duplicate this scenario. Interestingly if I disable all the other oscillators ( i.e. s->enable ( OSC_X , false ); ) the problem still remains. Whatever is causing the problem appears to be coming from the oscillator itself. I will continue to investigate ...
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #87

  • gslavenburg
  • gslavenburg's Avatar
I dumped all oscilator registers, and can confirm that the only difference between the two cases is the ovf/reset bit in control.

So it seems that the sound is coming from the oscilator and is only present when you do not allow the self reset on overflow. That is strange - a wavetable synthesizer should work fine without a reset on overflow. I wonder if there is some logic error that occurs on overflow, where the phase value is off by a small amount, causing some low amplitude second order phenomenon.

Anyway, for my application, 1953 Hz is fine. I'm using the osc as source to test speaker impedance, and the difference between measuring at 1953 Hz and 2 kHz is negligible. So I'm not 'stuck' on this - but my curiosity is peaked. I'll try and capture samples and do some frequency analysis and see if I can figure out what's going on.

By the way, the 'steps' that you see on your scope are real. The GinSing is approximating a sinewave and making discrete steps at the sampling rate. The two stage RC filter tries filter that out and smoothe the waveform, but it's not a good enough LPF to really get rid of the steps. You don't hear overtones because they are above human ear response. Actually, that RC filter is set at a very low frequency cutoff, causing the GinSing to have much more amplitude for low frequency than for for example 2 kHz. This is partly why the sound is a bit muffled in speech/music - the high notes are supressed. A higher order (active) LPF that gets rid of the sampling artefacts without surpressing high notes might be better.

best regards, Gerrit
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #88

Yes, I have been looking at this problem today, and so far it appears to be an inherent issue with the use of the overflow bit. I have confirmed this by toggling the bit on and off to see the problem come and go, all the while making sure all other oscillators are disabled. This code might be of some use in your testing:
// bits 0-2 ( 0x1, 0x2, 0x4 ) waveform type
// bit    3 ( 0x08 ) ABS/FULL bit
// bit    4 ( 0x10 ) overflow bit
// bit    5 ( 0x20 ) apply bend bit
// bit    6 ( 0x40 ) unused
// bit    7 ( 0x80 ) on/off


#define TEST_BIT 0x10


  ubyte regStatus; char msg[60];

  while ( 1 )
 {
   
   // clear overflow bit
   
   regStatus = GS.readRegister ( A1_Control );  // read current value
   regStatus &=  ~( TEST_BIT );                 // clear bit
   GS.sendCommand ( WriteOneByte , A1_Control , regStatus );

   
   printOscStatus( "A1 OVERFLOW OFF" );
   delay ( 1000 );

   
   
   // set overflow bit
   
   regStatus = GS.readRegister ( A1_Control );  // read current value
   regStatus |= ( TEST_BIT );                    // set bit
   GS.sendCommand ( WriteOneByte , A1_Control , regStatus );     
   
   printOscStatus( "A1 OVERFLOW ON" );
   delay ( 1000 );

 }



void printOscStatus( char *label)
{
  GSRegister oscCtrlRegs[6] = { A1_Control , A2_Control , A3_Control , B1_Control , B2_Control , B3_Control };
  ubyte regStatus;
  char msg[30];
  
  Serial.println ( "\n" );
  Serial.println ( label );
  
  for ( int oscIdx = 0; oscIdx < 6; oscIdx++ )
  {
     regStatus = GS.readRegister ( oscCtrlRegs[oscIdx] );
     sprintf ( msg , "osc #%d : 0x%.2x" , oscIdx , regStatus );
     Serial.println ( msg );
  }  
}

When I run this, I can hear (and see) the difference, and only the overflow bit is being set:
A1 OVERFLOW ON
osc #0 : 0x90
osc #1 : 0x00
osc #2 : 0x00
osc #3 : 0x00
osc #4 : 0x00
osc #5 : 0x00


A1 OVERFLOW OFF
osc #0 : 0x80
osc #1 : 0x00
osc #2 : 0x00
osc #3 : 0x00
osc #4 : 0x00
osc #5 : 0x00

Also, although there is definite stepping on the output as a result of the PWM conversion, I also see my A/D sampler stepping at its sampling rate ( 44.1 kHz ). I am in the process of getting up some pics of this issue as well as making a recording that I will forward onto Savage industries to get their take on this.
Last Edit: 6 years 7 months ago by administrator.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #89

I have started documenting this artifact. I'll be putting in some more info ( i.e. spectrographs ) that will show this issue, but hopefully the recordings give you an idea of what I think you are also hearing.

article on DCO OVF bit artifact
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #90

  • gslavenburg
  • gslavenburg's Avatar
Nice writeup, but I believe you used the words enabled/disabled inverted.

The artifact is there when the Ovf/reset is disabled (and the frequency is 2000 Hz)
The artifact is absent when the Ovf/reset bit is set (and the frequency is 1953 Hz).

The artifact indeed sounds similar to what I hear.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #93

Ah, yes - thanks, it should be correct now.
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #96

I can confirm this same issue, but I noticed it because I couldn't do smooth pitch bends while a note was active.
my code looks like:

GinSingSynth *poly = GS.getSynth();
poly->begin();
poly->setPatch(OSC_1_TO_MIXER);
poly->setEnvelope ( OSC_ALL , AT_2MS , 1.00f , DR_10MS , 0.40f , DR_145MS , 0.0f );
// poly->setWaveform(OSC_1, SINE);
poly->enableBend(OSC_1, true);
poly->setFrequency(OSC_1, freq);
poly->trigger(OSC_1);
for(int i = 0; i <= 2000; i++){
sensorValue = analogRead(sensorPin);
float freq = rescale((float)sensorValue, 0.0f, 1023.0f, 80.0f, 880.0f);
freq = smooth(freq);
Serial.println(freq);
poly->setFrequency(OSC_1, freq);
}
poly->release(OSC_1);


if I uncomment the line:
// poly->setWaveform(OSC_1, SINE);
I get a "stepped" sound as I adjust my sensor (a flex sensor in this case)
removing that line, I can a nice smooth pitch transition.

Which is much nicer sounding, but I'd like to use other waveforms than SINE. How can I do that, and still get the smooth pitch transitions?

Thanks for this awesome product!
The administrator has disabled public write access.

Re: can't seem to set accurate frequency in Synth mode 6 years 7 months ago #97

Thanks for the nice comments. In the current setWave() function, you can see the method by which the overflow bit is being set. We have found a bug in that code as it appears that changing waveforms does not handle the overflow bit properly. I intend to add a function to do this to make it more controllable and transparent ( i.e. setOverflow() ), but in the meantime, you can use the following code to set the overflow bit:
// bits 0-2 ( 0x1, 0x2, 0x4 ) waveform type
// bit    3 ( 0x08 ) ABS/FULL bit
// bit    4 ( 0x10 ) overflow bit
// bit    5 ( 0x20 ) apply bend bit
// bit    6 ( 0x40 ) unused
// bit    7 ( 0x80 ) on/off


#define TEST_BIT 0x10 // test overflow bit

ubyte regStatus;


// clear test bit
// ----------------------------------------------------------------------

// method 1 - read the register and update whole byte

   regStatus = GS.readRegister ( A1_Control );  // read current value
   regStatus &=  ~( TEST_BIT );                 // clear bit
   GS.sendCommand ( WriteOneByte , A1_Control , regStatus );


// method 2 - write the bit with a mask

   GS.sendCommand ( WriteOneByteWithMask , A1_Control , TEST_BIT ,TEST_BIT );



// set test bit
// ----------------------------------------------------------------------


// method 1 - read the register and update whole byte

    regStatus = GS.readRegister ( A1_Control );  // read current value
    regStatus |= ( TEST_BIT );                    // set bit
    GS.sendCommand ( WriteOneByte , A1_Control , TEST_BIT );


// method 2 - write the bit with a mask

    GS.sendCommand ( WriteOneByteWithMask , A1_Control , TEST_BIT , TEST_BIT );

This code shows two methods to set the overflow bit using the function sendCommand(). The register A1_Control should reflect the DCO you want to play with as defined in GinSingDefs.h.

I would recommend starting with the simple masked bit setting operation, and if that does not make a difference try using the one with the register read. The former is more efficient, but I have noticed that it seems that under certain conditions the bit is sticky; perhaps to microcode makes sure the proper 'default' settings are not changed or something - still looking into that.

Let me know if that helps.
Last Edit: 6 years 7 months ago by administrator.
The administrator has disabled public write access.
  • Page:
  • 1
Time to create page: 0.283 seconds