sweep sine tone generation artifacts

Hello to all,

I want to generate a wave file with a sweeping sine for example from 1000 Hz to 1200 Hz in 0.3 seconds increasing with 1 Hz steps.
For this I thought that I have to have always a full phase (returning to zero) before I can change the fequency to the next higher step. But I hear an artifact in the sweeping sine tone so that the tone is not completely smooth. In one phase I do calculate nearly the full phase (full phase - 1 sample) and the next higher frequency begins again with zero.

I use two functions:

(1) calculate a number of equal frequency phases (these are smooth without artifacts)


Function mdGenWavDataXperiods(aFrequency as Integer, aNumOfPeriods as integer) As MemoryBlock
  // self.sampleRate As integer = 44100  Hertz
  
  dim wavSampleCount As integer = ((self.sampleRate / aFrequency) * aNumOfPeriods)   //generating of one period for a given frequency
  
  dim m As new MemoryBlock(wavSampleCount)
  
  // self.twoPi As double = 6.28318
  dim timeScale As double = (self.twoPi / self.sampleRate)
  dim lastSample As integer = wavSampleCount - 1
  dim t As double
  dim sinVol as integer = 127
  
  for i As integer = 0 to lastSample
    t = i * timeScale
    m.UInt8Value(i) = 127 + sinVol * sin(aFrequency * t)   // sine
  next
  
  return m
  
End Function

(2) in the next function I add different frequencies one after the other


Function mdGenGlideWavDataTEST() As MemoryBlock

  dim mbArr() as MemoryBlock
  for iFreq as integer = 1000 to 1200
    mbArr.Append( self.mdGenWavDataXperiods(iFreq, 2) )    
  next iFreq
  
  // calc total size for mbArr
  dim mbArrSize As integer
  for i as integer = 0 to mbArr.Ubound
    mbArrSize = mbArrSize + mbArr(i).Size
  next i
  
  // copy the different MemoryBlocks into one MemoryBlock 'm'
  dim m as new MemoryBlock(mbArrSize)
  dim iSampleCounter as integer = 0
  for i as integer = 0 to mbArr.Ubound
    for j as integer = 0 to mbArr(i).Size - 1
      
      m.Int8Value(iSampleCounter) = mbArr(i).Int8Value(j)
      iSampleCounter = iSampleCounter + 1
    next j
    
  next i
  return m
  
End Function

and then I add the WAV file header


Function createGlidingToneTEST(aToneFreqStart as integer, aToneFreqDifference as integer, aToneDuration as double) As String
  if self.sound <> nil and self.sound.IsPlaying then
    self.sound.stop
  end if
   
  dim firstToneFreq, secondToneFreq as integer
 
   dim waveDataGliding As MemoryBlock = mdGenGlideWavDataTEST()
   dim fileDataGliding As MemoryBlock = mdCreateWavFileData(waveDataGliding)
   dim filenameStr as String = "sine_glide_" + Str(firstToneFreq) + "_" + Str(aToneFreqDifference) + "_" + Str(self.filenum) + ".wav"
  
  #if DebugBuild and TargetWindows then
    self.wavFile = GetFolderItem("").Parent.Child("stim").Child( filenameStr )
  #else
    self.wavFile = GetFolderItem("").Child("stim").Child( filenameStr )
  #endif
 
  dim bs As BinaryStream = BinaryStream.Create(self.wavFile, true)
  bs.Write(fileDataGliding)
  bs.Close
 
  Return "" 
End Function

Does anyone see the problem that could be the reason for an artifact or does anyone have a suitable code for sweep tone generation?
Any help is appreciated.
Thank you.
Thomas

Thomas, asking the same or similar question in new topics every few days, will not increase the chance of getting an answer, no improve the quality of the answer. Usually if you don’t get a response, it is because the specific topic is no one that somebody else has been dealing with, and therefore cannot supply an answer, or there is a person with the answer you seek, but they have not seen nor had the time to respond

Hello Dave,

it is not the same question. The other question about normal sine waves is answered (thank you to Will), you can see it here

https://forum.xojo.com/36209-problem-with-end-of-sine-wave-click-crack

This question is different from the other and not “similar”. The other one was about sine wave generation and clicks at the end, this one is about artifacts when I generate a sweep (gliding) tone.
So I try. If noone has an answer I will ask in another forum. But I know there were some debates about wave generation in this forum so I try one’s luck.

Thomas

You might want to consider generating your sine waves using the method of direct digital synthesis (DDS) that is used in solid state hardware. Create a sine wave lookup table containing the values for one complete cycle. Then step through the table using an incremental index that depends on the frequency you’re generating, and your sample rate. As you sweep up or down in frequency, only the increment changes, while the last position in the table stays the same. So, you don’t create transient changes when your frequency changes. While I mentioned a lookup table that is the way that it is done in hardware, but unnecessary for your application. You would simply implement the same method but use the sin() function to get the values. For your purposes, you would calculate the increment based on frequency and sample rate, and then your indexing of the sin function would be as follows:

sinIndex=0
increment= 'calculate your increment based on frequency and sample rate
while
   sinIndex=sinIndex+increment
   if sinIndex>2*pi then sinIndex=sinIndex-2*pi
   output=sin(sinIndex)
   'Put code here to change increment value for frequency sweep
   '
   '
wend