Why is "AppleSequencer" limited to 280.00 BPM? - audiokit

I've started using AppleSequencer in my app and was wondering why it is limited to 280bpm?
When setting tempos above 280bpm like sequencer.setTempo(BPM(300.00)) the sequencer still plays and returns 280.00 in sequencer.tempo
Would be awesome to make faster tempos possible. If not it would be great to get a warning in the console when setting tempos above 280.

The setTempo method in AppleSequencer.swift clamps that value to the range of 10 to 280.
let constrainedTempo = (10 ... 280).clamp(bpm)
You could write a Pull Request to add a comment to setTempo in AppleSequencer.swift.
if bpm > 280 || bpm < 10 { Log("bpm out of range") }

Christian,
If you use the AudioKit 5 Sequencer that's available when you import AudioKit and AudioKitEX from the Swift Package Manager, it doesn't have a tempo limit.
sequencer.tempo = 300

Related

AudioKit - Trying to generate sound in Audio Kit 5

I am setting up a start application that on start up, will generate some white noise using AudioKit.
I have set up the following code that gets called on start up of my application:
let engine = AudioEngine()
let noise = WhiteNoise()
let mixer = Mixer(noise)
mixer.volume = 1
engine.output = mixer
try! engine.start()
But when I start up the application I do not hear any sound being generated. I set up a simple example to generate a sine wave using AVFoundation and I was able to hear the sound generated from my simulator.
I found an old thread - AudioKit - no sound output but I checked the AudioKit repo and it looks like this feature was removed a couple months back since it was not being used.
Any help would be appreciated!
Try noise.start() Generators don't default to being on.

AudioKit: how to perform frequency modulation for AKPlayer

I'm trying to perform frequency modulation on a signal coming from AKPlayer, which in return plays a mp3 file.
I've tried to work with AKOperationEffect, but it doesn't work as expected:
let modulatedPlayer = AKOperationEffect(player) { player, _ in
let oscillator = AKOperation.fmOscillator(baseFrequency: modulationFrequency,
carrierMultiplier: player.toMono(),
modulatingMultiplier: 100,
modulationIndex: 0,
amplitude: 1)
return oscillator
}
Has anybody an idea how to get the mp3 modulated?
Unfortunately, the AudioKit API is not so well documented .... there are a tons of examples, but they all deal with synthetic sounds such as sine, square waves etc.
I took the time to create a working practical example to help you #Ulrich, you can drop and play if you have the playground environment available, or just use it as a reference trusting me it works to amend your code, it's self-explanatory but you can read more about why my version work after the code TLDR;
Before <audio>
After <audio>
The following was tested and ran without problems in the latest XCode and Swift at the time of writing (XCode 11.4, Swift 5.2 and AudioKit 4.9.5):
import AudioKitPlaygrounds
import AudioKit
let audiofile = try! AKAudioFile(readFileName: "demo.mp3")
let player = AKPlayer(audioFile: audiofile)
let generator = AKOperationEffect(player) { player, _ in
let oscillator = AKOperation.fmOscillator(baseFrequency: 400,
carrierMultiplier: player.toMono(),
modulatingMultiplier: 100,
modulationIndex: 0,
amplitude: 1)
return oscillator
}
AudioKit.output = generator
try! AudioKit.start()
player.play()
generator.start()
Find the playground ready to use in the Download page ( https://audiokit.io/downloads/ )
As you can see, apart from declaring a path to the mp3 file when initializing a new AKAudioFile and passing to an AKPlayer instance, there are three steps that you need to occur in a certain order:
1) Assign an `AKNode` to the AudioKit output
2) Start the AudioKit engine
3) Start the `player` to generate output
4) Start the generator to moderate your sound
The best way to understand why this is to forget about code for a bit and imagine patching things in the real world; and finally, try to imagine the audio flow.
Hope this helps you and future readers!

URLSessionDownloadDelegate progress not updating

I'm quite new to the topic of IOS development, so it's may a stupid question, but I'm unable to calculate and print the progress of a download task using URLSessionDownloadDelegate.
I was following this guide: https://medium.com/swlh/tracking-download-progress-with-urlsessiondownloaddelegate-5174147009f and its source code from https://github.com/ShawonAshraf/URLSessionProgressTrackerExample but the progress label just jumps from 0 to 100% even with bigger files, which require a few minutes to download.
If it's possible to do so, I would like not to use a third party lib.
I'm using swift 5 with Xcode 11.4 on an iOS 13.4 simulator.
The sample project you've linked performs integer division to calculate the progress, and therefore only ever gives you 0 or 1 as the result.
Replace this line
let percentDownloaded = totalBytesWritten / totalBytesExpectedToWrite
with this
let percentDownloaded = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)

Playing multi-sampled Instruments using AudioKit, controlling ADSR envelope

I'm trying to play instrument of several .wav samples using AudioKit.
I've tried so far:
Using AKSampler (with underlying AVAudioUnitSampler) – it worked fine, but I can't figure out how to control ADSR envelope here – calling stop will stop note immediately.
Another way is to use AKSamplePlayer for each sample and play it, manually setting rate so it play the right note. I can (possibly?) then connect AKAmplitudeEnvelope to each sample player. But if I want to play 5 notes of the same sample simultaneously, I would need 5 instances of AKSamplePlayer, which seems like wasting resources.
I also tried to find a way to just push raw audio samples to the AudioKit output buffer, making mixing and sample interpolation by myself (in C, probably?). But didn't find how to do it :(
What is the right way to make a multi-sampled instrument using AudioKit? I feel like it must be a fairly simple task.
Thanks to mahal tertin, it's pretty easy to use AKAUPresetBuilder!
You can create .aupreset file somewhere in tmp directory and then load this instrument with AKSampler.
The only thing worth noting is that by default AKAUPresetBuilder will generate samples with trigger mode set to trigger, which will ignore note-off events. So you should set it explicitly.
For example:
let sampleC4 = AKAUPresetBuilder.generateDictionary(
rootNote: 60,
filename: pathToC4WavSample,
startNote: 48,
endNote: 65)
sampleC4["triggerMode"] = "hold"
let sampleC5 = AKAUPresetBuilder.generateDictionary(
rootNote: 72,
filename: pathToC5WavSample,
startNote: 66,
endNote: 83)
sampleC5["triggerMode"] = "hold"
AKAUPresetBuilder.createAUPreset(
dict: [sampleC4, sampleC5],
path: pathToAUPresetFilename,
instrumentName: "My Instrument",
attack: 0,
release: 0.2)
and then create a sampler and start AudioKit:
sampler = AKSampler()
try sampler.loadInstrument(atPath: pathToAUPresetFilename)
AudioKit.output = sampler
AudioKit.start()
and then use this to start playing note:
sampler.play(noteNumber: MIDINoteNumber(63), velocity: MIDIVelocity(120), channel: 0)
and this to stop, respecting release parameter:
sampler.stop(noteNumber: MIDINoteNumber(63), channel: 0)
Probably the best way would be to embed your wav files into an EXS or Soundfont format, making use of tools in that realm to accomplish the ADSR for instance. Otherwise you'll kind of have to have an instrument for each sample.

How to get current stream position using GoogleCast frameWork in iOS

I am working on an application in which I will connect to the T.V using ChromeCast device, to achieve this I have used GoogleCast FrameWork in my project,
I am facing a problem when I try to access the approximate stream position of the video using the below statements,
GCKMediaControlChannel *mediaControlChannel = [[GCKMediaControlChannel alloc] init];
NSLog(#"Approximate stream position is %f",mediaControlChannel.approximateStreamPosition);
But this is resulting in a time difference of 20 seconds.
I tried below statements to get the exact stream position,
GCKMediaStatus *deviceStatus = [[GCKMediaStatus alloc] initWithSessionID:sessionId mediaInformation:self.mediaInformation];
NSLog(#"Stream Position %f", self.deviceStatus.streamPosition);
As the above method is having two parameters,We need to send session as an integer, but we are getting session id as a string alpha numeric and upon converting this to integer resulting in 0.
Can any one help me to get the session ID as an integer, Or suggest me to get the current stream position with any different method.
I use the following code to retrieve the stream position of the video that is currently being casted, and it's pretty accurate! The Google Cast SDK version that we use in our project is 3.5.3.
let position = Double(GCKCastContext.sharedInstance().sessionManager.currentSession!.remoteMediaClient!.mediaStatus!.streamPosition)
Hope it helps!
approximateStreamPosition should give you a pretty accurate time, certainly not off by 20 seconds. You can take a look at our iOS reference app for an example.
You can use approximateStreamPosition for the same.
Below code will print the more accurate time.
if let position = GCKCastContext.sharedInstance().sessionManager.currentSession?.remoteMediaClient?.approximateStreamPosition() {
print("current time ",position)
}

Resources