Any can help with the problem of glide effect with using oscillator.
Here is the part of code, I need that every cycle oscillator sounds on new random frequency. But frequencies are changed smoothly with glide effect. How to remove glide effect?
for _ in 1...20 {
oscillator.frequency = Double.random(in: 0...10000)
oscillator.start()
sleep(1)
oscillator.stop()
}
Try adding oscillator.rampDuration:
oscillator.frequency = Double.random(in: 0...10000)
oscillator.rampDuration = 0.0
oscillator.start()
sleep(1)
oscillator.stop()
Related
I'm new to AudioKit and am using v5. The oscillator frequency ramp doesn't seem to work as expected. The following example has 2 successive ramps. First it ramps 440-880, but then sounds like it goes 880-660 instead of 440-660.
If I comment out osc.$frequency.ramp(to: 660.0, duration: 1.0), it ramps 440-880, then ramps extremely quickly to 440 but gets there.
Seems like something isn't resetting after the ramp.
(The sleeps are only for testing.)
Is this a bug? Is there something else I should be doing? Any insight would be much appreciated! Thanks!
import Cocoa
import AudioKit
class Test {
let akEngine = AudioEngine()
let osc = Oscillator()
func setup() {
osc.amplitude = 0.1
akEngine.output = osc
do {
try akEngine.start()
} catch {
print("Couldn't start AudioEngine.")
}
osc.frequency = 440.0
osc.start()
osc.$frequency.ramp(to: 880.0, duration: 1.0)
sleep(2)
osc.stop()
sleep(1)
osc.frequency = 440.0
osc.start()
osc.$frequency.ramp(to: 660.0, duration: 1.0)
sleep(2)
osc.stop()
}
}
This probably deserves an explanation, or maybe it should be fixed to work as you have it above, but once you start automating changes, you should stick with the automation syntax and not jump out to plain setting of values. For you this means just replacing osc.frequency = 440 with osc.$frequency.ramp(to: 440.0, duration: 0.0) and I believe you will get the effect you want.
Setting a parameter (osc.frequency = 440.0) causes a tiny ramp to be used to avoid zippering (equivalent to osc.$frequency.ramp(to: 440.0, duration:epsilon)). The test code immediately applies another ramp, overriding the zippering ramp.
If you insert a sleep after your second osc.start(), you'll hear the quick zipper ramp back to 440.
If I use AKOscillator only for specific purpose, should I anyway use Envelopes classes to avoide
amplitude click when I start/stop oscillator?
Or there any other more light methods?
One "light" method is to set your parameter ramp to a non zero value, start your amplitude at zero, and then set your amplitude. Ramping is the same value for all parameters, though, so depending on if you want your frequency to change at a different ramp, you may want to change the ramp again after it has reached the amplitude you want.
Here's an example playground:
import AudioKitPlaygrounds
import AudioKit
let oscillator = AKOscillator(waveform: AKTable(.sine), amplitude: 0)
oscillator.rampDuration = 0.2
AudioKit.output = oscillator
try AudioKit.start()
oscillator.start()
oscillator.amplitude = 1.0
sleep(1)
oscillator.amplitude = 0
I used your code and it did not help, but I found out that this 'click' appears on the end, when oscillator stops. so if even rampDuration is 0.0, there is not 'click' at the start, the only 'click' is on the end. Here is my code (it is inside IOS app):
class ViewController: UIViewController {
var osc = AKOscillator(waveform: AKTable(.sine), amplitude: 0)
#IBAction func buttonTapped(_ sender: UIButton) { //when button in App is pressed
osc.rampDuration = 0.2
AudioKit.output = osc
osc.frequency = Double.random(in: 100.0...1000.0)
try? AudioKit.start()
osc.start()
osc.amplitude = 0.5
osc.rampDuration = 0.0 //to avoid frequency glide effect
sleep(1)
//osc.rampDuration - I tried to change rampDuration before oscillator stop, but it
//did not help
osc.stop() //here is amplitude 'click' appears
try? AudioKit.stop()
}
So, as I supposed I have to use envelopes anyway?
We are using two AKMixer (one for left, one for right channel) and one AKMixer as output with these two mixers as inputs.
If one of the mixers has a volume lower than 0.00001 the output signal is lost. But lower volumes are possible, because if we lower the main system volume on values over 0.00001 the signal on the headphone-jack is going lower.
As a workaround I tried to set the AKMixer.output.volume to 0.5 and the input mixers to 0.00001 and it works too. But in my application I also need max output and than I got weird "clicks" when changing the both volume levels at once.
It would be great if somebody can help. With the workaround or the causing problem.
Thanks.
var rightSine = AKOscillator(waveform: AKTable(.sine))
var rightPanner : AKMixer!
let pan2 = AKPanner(self.rightSine, pan: 1)
pan2.rampDuration = 0
let right1: AKMixer = AKMixer(pan2 /*, .... some more */)
self.rightPanner = right1
let mix = AKMixer(self.rightPanner /* left channel... */)
mix.volume = 1.0
AudioKit.output = mix
do {
try AudioKit.start()
} catch {
}
self.rightPanner.volume = 0.00002
This is the code used to initialise the audio stuff (shortened) and afterwards the nodes are started.
*Edit: I'm testing the precise threshold on which the output is broken..
AudioKit's AKMixer is a simple wrapper around Apple's AVAudioMixerNode and as such, I can't really dig much deeper to help you solve the problem using that node. But, if you're willing to switch to AKBooster, whose job it is to amplify or diminish a signal, I think you will be fine to use small numbers for your gain value.
var rightSine = AKOscillator(waveform: AKTable(.sine))
var rightBooster: AKBooster!
let pan2 = AKPanner(self.rightSine, pan: 1)
pan2.rampDuration = 0
let right1: AKMixer = AKMixer(pan2 /*, .... some more */)
self. rightBooster = AKBooster(right1)
let mix = AKMixer(self. rightBooster /* left channel... */)
mix.volume = 1.0
AudioKit.output = mix
self.rightBooster.gain = 0.00002
How can I pan an oscillator to one ear using AudioKit? This is what I have right now:
oscillator = AKOscillator()
leftPan = AKPanner(oscillator, pan: -1)
mix = AKMixer(leftPan, oscillator)
AudioKit.output = mix
AudioKit.start()
mix.start()
leftPan.start()
oscillator.start()
However, the sound is still playing in both ears.
How can I fix this?
Try this:
oscillator.start()
leftPan = AKPanner(oscillator, pan: -1)
AudioKit.output = leftPan
AudioKit.start()
You seem to not even need the mixer. My guess is that it's redundant, which messes up the pan.
Source.
The root cause of the sound being in both ears is mixing the original oscillator, which is mono (not panned). DopApps's answer is correct: simply assign "leftPan" to the AudioKit.output.
In a game I'm developing with SpriteKit, I want certain objects to appear and shrink. I already know how to scale them down, and I'm achieving this using the following code:
myNode.run(SKAction.scale(to: 0, duration: 3))
However, the shrinking happens 'linearly'. Is there a way to make it shrink exponentially faster? Or at least that it starts slowly and at the last second it shrinks twice as fast?
Sorry I could not test this out, I do not have a compiler. It is properly not the best way to do it, but I gave it a shot:
func delay(_ delay:Double, closure:#escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when, execute: closure)
}
let totalRunTime = 1
var add = 0.0
var scale = 1
var done = false
while !done{
delay(add, closure: {
add += 0.1
scale = 1 - (add ^2)
myNode.run(SKAction.scale(to: scale, duration: totalRunTime / 10))
})
if add == 0{
done = true
}
}
Edit: When I look at my code I may see a bug: maybe you need to switch the exponential formula from scale to duration to make it work, I can not test it now :(
Have a look at the Sprite Kit Utils from Ray Wenderlich. It's quite a useful library and also provides easing functions for movement, scale, and rotate actions.
(For reference, have a look at the different easing functions demonstrated on easings.net)
Hope that helps!