problem with end of sine wave click/crack

I want to use a slightly changed run method that I have found in the MBS example (PortAudio).

I want to present two sinus sonds with a given duration with a pause between them (the pauses and so on are not the problem, I use timer). After playing a sinus sound I got always something like a stopping “click” in the sound. The sinus sound does not end with silence it ends with something like a “click” or “crack”. Is there a possibility to prevent this (or why does this happens?). Has anyone this problem before and a solution?

At the moment I use XOJO Version 2016 1.1 on my Mac but I also want to use the sinus sound presentation on Windows 7 and the “click”/“crack” is the same there.

This is my currently code:



  #pragma StackOverflowChecking false
  #pragma DisableAutoWaitCursor
  #pragma DisableBackgroundTasks
  #pragma DisableBoundsChecking
  
  const delta=0.01000
  
  dim n,c,i as integer
  dim f as single
  

  c=FrameCount-1
  
  // calculate all possible outside the for loop
  dim fixVal as double = ( 2.0 * 3.14159265358979323846264338327950 / 44100)
 
 // tones.pitch ==> module-Variable e.g. 1000 Hz
  System.DebugLog("  pitch=" + Str(tones.pitch))
  
  for i=0 to c

    f= tones.sinVolume * sin(timeIndex * fixVal * tones.pitch )
    timeIndex=timeIndex+1
    
    outputBuffer.SingleValue(n)=f // left
    n=n+4
    outputBuffer.SingleValue(n)=f // right
    n=n+4
  next
    

Is there a possibility to fade in/fade out the sine wave so that no “click”/“crack” will be heard? Does anyone know how to implement this with the MBS AudioPort functions?

Any help is appreciated. Thank you very much.
Thomas

To ramp down just multiply the signal with linearly decreasing values. something like this placed after your code…

[code]dim rampSamples As integer = 20 //change this to how long of a ramp you want
dim rampStartSample As integer = (c - rampSamples) * 8
dim v As Single

for i = 0 to rampSamples
n = rampStartSample + i * 8
v = 1 - i / rampSamples //v ramps from 1 to 0 as i steps from 0 to rampSamples
outputBuffer.SingleValue(n) = v * outputBuffer.SingleValue(n)
outputBuffer.SingleValue(n+4) = v * outputBuffer.SingleValue(n+4)
next[/code]

Untested so may need tweaks.

I use now the mdCreateWaveData and mdCreateWaveFileData from an example in this forum (tone_generator_hearing_test.xojo_binary_project).
This functions generate a real wav-file and the mdCreateWaveFileData is a implementation of Will Shank, thank you :slight_smile: .

Now I can fade in/out the sine wave with a linear function. The extended funtion is below. Differences are that the variable seconds is now a double for lower durations as a second and there some other small adaptions.

Function mdGenWavData(seconds as double) As MemoryBlock
  dim wavTime As Double = seconds
  // self.sampleRate = 44100
  dim wavSampleCount As integer = (self.sampleRate * wavTime)   //gen 2 seconds of samples
  dim m As new MemoryBlock(wavSampleCount)
  
  // self.twoPi = 6.28318 = 2 * PI
  dim timeScale As double = (self.twoPi / self.sampleRate)
  dim lastSample As integer = wavSampleCount - 1
  dim t As double
  dim sinVol as integer = 127
  
  // calculate sine wave for a given time (seconds)
  for i As integer = 0 to lastSample
    t = i * timeScale
    m.UInt8Value(i) = 127 + sinVol * sin(self.frequency * t)   // sine
  next
  
  // calculation for fade in
  // new sinVol for linear fade in as a part of wavSampleCount approxim. 25 ms
  dim lowerArr(127*10) as Double
  for i as integer = 0 to lowerArr.Ubound
    lowerArr(i) = (i/lowerArr.Ubound)
  next
  
  // change the first 101 samples into zero
  for i as integer = 0 to 100
    lowerArr.Insert(0, 0.0)
  next
  
  // change the volume for the samples at the beginning of sine wave
  for i as integer = 0 to lowerArr.Ubound
    m.UInt8Value(i) = ((m.UInt8Value(i) - sinVol) * lowerArr(i)) + sinVol
  next i
  
  // use the calculation for fade in here to fade out the last samples
  dim idx as integer = -1
  for i as Integer = lastSample DownTo lastSample - lowerArr.Ubound
    idx = idx + 1
    m.UInt8Value(i) = ((m.UInt8Value(i) - sinVol) * lowerArr(idx)) + sinVol
    
  next i
  
  return m
  
End Function

Thank you for the idea Will.

Best wishes
Thomas