AKPanner node not affecting output - swift

I've been struggling with this for a while now.
I've got an array of AKPlayers.
var players = [AKPlayer]()
Then I create an AKPanner node, set the pan, and connect it into the input of an AKMixer
let playerNode = AKPlayer(audioFile: c.audioFile!)
playerNode.pan = 0
var pannerNode = AKPanner(playerNode, pan: 1)
self.audioMixer.connect(input: pannerNode)
players.append(playerNode)
panners.append(pannerNode)
I also throw the nodes into an array due to this
Then I do the following:
do {
AudioKit.output = audioMixer
try AudioKit.start()
} catch {
print(error.localizedDescription)
}
I am able to hear sound, but it is in both ears. Not in my right ear.
Any help would be greatly appreciated. Thank you.

My problem was not with the code at all, but rather, with a setting on my phone.
Make sure that Mono Audio is turned off in the iOS settings under:
General > Accessibility > Mono Audio
**Note: Mono Audio is under the Hearing section

Related

Stop SKAudioNode from Playing

I am trying to play footstep sounds only when the player is moving. I added a check to see if the player is already moving to make sure it would not play audio on top of each other.
For some reason footstepSound.run(SKAction.stop()) is not working which is causing a bunch of tracks to play over each other which sounds very bad.
Any ideas?
let footstepSound = SKAudioNode(fileNamed: "Footsteps.mp3")
if (degree != 50) {
if (isFootstepping) { return }
isFootstepping = true
self.addChild(footstepSound)
}
else if (isFootstepping && degree == 50) {
isFootstepping = false
footstepSound.run(SKAction.stop())
footstepSound.removeFromParent()
}
Solved! The issue is that the footstepSound variable was not globally declared. This was causing a new variable to be created on each function call, therefore when .removeFromParent was called it was never referencing the old variable.

How to use the loop if the track was not started from the beginning (with buffering type = .always in AKPlayer )

I run several AKPlayer with different files and the same length - the first one starts from the beginning, the others start by the button relative to the time of the first. Files are seamless, worth buffering type = .always, loop = true. If AKPlayer did not start from the beginning, then only that part of the track from which the track began to play to the end, and when the loop occurs, starts StartTime is not a zero value. It is necessary that when a loop is played all the tracks from the beginning.
With AKWaveTable, everything works adequately, but there are no pan and pitch settings in the player.
Here is a sample code. In the original, I use an array of players and in a loop I upload all the files to my players. I’m doing something like drummachine - several audio files are playing, and I can turn on / off other files in parallel with respect to the time the player was first started. Each file is the same in duration. When I do the same in AKWaveTable, then everything works correctly, but in the future it does not suit me.
In this example, I run the playPlayer1 method first and after a while I run playPlayer2. When Player1 starts the loop from the beginning, then Player2 starts the loop from the previous currentTime (for example, from the middle of the file) and its length becomes equal forever (endTime - currentTime)
var player1: AKPlayer!
var player2: AKPlayer!
var playersMixer: AKMixer!
init() {
do {
let file1 = try AKAudioFile(readFileName: "Audio/file1.m4a")
let file2 = try AKAudioFile(readFileName: "Audio/file2.m4a")
player1.load(audioFile: file1)
player2.load(audioFile: file2)
} catch {
print(error.localizedDescription)
}
player1.buffering = .always
player1.isLooping = true
player2.buffering = .always
player2.isLooping = true
playersMixer = AKMixer (player1,player2)
AudioKit.output = playersMixer
do {
try AudioKit.start()
} catch {
print(error.localizedDescription)
}
}
func playPlayer1() {
player1.play()
}
func playPlayer2() {
player2.play(from: currentTime)
}
var currentTime: Double {
get {
if player1.isPlaying {
return player1.currentTime
}
return 0
}
}
I think that's a missing feature in AudioKit or a bug. Meanwhile, the current version does use the startTime for the loop points as we can see in the source code (https://github.com/AudioKit/AudioKit/blob/master/AudioKit/Common/Nodes/Playback/Players/Player/AKPlayer.swift)
Meanwhile, there's a solution I found and hope it's useful for other readers:
player.isLooping = false
player.buffering = .dynamic
player.completionHandler = {
player.isLooping = true
player.buffering = .always
player.play(from: 0, to: player.duration)
}
player.play(from: masterPlayer.currentTime)
What I'm doing is to create a player and set .isLooping and .buffering falsely and call .play to run it as a one-time, or a single shot play! A .completionHandler callback is called on complete, where I set .isLooping and .buffering positively. Finally, call .play setting the desired loop points using the properties from and to from self. The masterPlayer refers to a separate player that is used as a reference to get the current play position, I know it's easy to understand but just to avoid assumptions.
EDIT:
After going throw tests, I found an issue that I've reported and deleted before (Is synchronised looping supported for AKPlayers that are multiples in their duration?) and had to reopen, so hopefully, I get an answer and will help understand if it's supposed to work or not.
Also forced player to detach and created a new one:
player.completionHandler = {
player.detach()
let player = self.createPlayer(audioFile: audioFile)
self.connectPlayerToMixer(player)
player.isLooping = true
player.buffering = .always
player.startTime = 0
player.endTime = audioFile.duration
player.play(at: AVAudioTime.now())
}
I've now tested AKWaveTable and hopefully, I did it correctly but it also fails just after the recording that is twice the size of previews recording, for example:
Loop1 > 1 2 3 4
Loop2 > 1 2 3 4
Loop3 > 1 2 3 4 5 6 7 8
Loop4 > 1 2 3 4
Loop5 > 5 6 7 8
(recorded as 1 2 3 4 5 6 7 8, but plays back as 5 6 7 8)
I'll have to go back and test the original AKNodeRecorder to see if the behaviour is similar, but for the moment I'll try another tests with AKWaveTable.
After some time testing * *
Here's the audio recording describing the issue above:
https://drive.google.com/open?id=1zxIJgFFvTwGsve11RFpc-_Z94gEEzql7
After looking at the problem for some time, and all the research I found what seems to be a solution. By shifting the procedure that is used! Instead of setting the player to start along the current time, should instead schedule it to start from the start time. This because the start time is what is used for the loop start and endpoints! To learn a bit more follow the link to another StackOverflow post I've posted before (Solution is presented here (Is synchronised looping supported for AKPlayers that are multiples in their duration?), thanks!

Unity OnMatchList inaccesible due to its protection level

I have seen that there are more answers to similar questions, but none of these helped me. I hope you can.
I have a Unity2D shooter game and I try to make a menu for UNET. I watched a youtube tutorial from Brackeys to make the menu (https://youtu.be/V4oRs26vAw8?list=PLPV2KyIb3jR5PhGqsO7G4PsbEC_Al-kPZ&t=896) and when he runs the project it shows me the error: "error CS0122: 'UnityEngine.Networking.Match.ListMatchResponse' is inaccessible due to its protection level. I found out that this might happen when you access for example a private variable from another function, but I access a function from Unity and I can not modify its type (I believe). Any ideas? Thank you.
public void OnMatchList(bool success, string extendedInfo, ListMatchResponse matchList)
{
status.text = "";
if (matchList == null)
{
status.text = "Couldn't get room list.";
return;
}
ClearRoomList();
foreach(MatchDesc match in matchList.matches)
{
GameObject _roomListItemGO = Instantiate(roomListItemPrefab);
_roomListItemGO.transform.SetParent(roomListParent);
// Have a component sit on the gameobject
// that will take care of setting up the name / amount of users.
// as well as setting up a callback function that will join the game.
roomList.Add(_roomListItemGO);
}
}
'MatchDesc' has been renamed to 'MatchInfoSnapshot'.
Just replace it and it should work fine.

Webaudio :: Play Recorded Audio

I want to play the recorded audio using microphone.
After recording it as 32 bit arrays
let left = e.inputBuffer.getChannelData(0);
let tempLeftChannel = this.state.leftChannel;
tempLeftChannel.push(new Float32Array(left));
this.setState({ leftChannel: tempLeftChannel });
Now In the leftChannel array, I had chunk of audio data. Now, I want to play them in the browser. How can I do that?
You leave quite a bit out from your snippet, but perhaps the following will give you an idea of one way to play out the float array that you have. Let context be the AudioContext that you probably have.
let buffer = new AudioBuffer({length: leftChannel.length,
sampleRate: context.sampleRate});
buffer.copyToChannel(leftChannel, 0);
let source = new AudioBufferSourceNode(context, {buffer: buffer});
source.connect(context.destination);
source.start();

Change the color of all nodes in a scene?

So this may seem like a stupid question; however, I'll see if anyone has an answer.
Is there any way to change the color of all nodes in a scene in swift? For example invert all the colors?
I've created a game using SpriteKit and would like to create different themes. Instead of changing every node one by one. I would like to at least do most in one shot. If anyone has any advice that would be greatly appreciated! Thanks!
-Matt
Inside of the scene you want,
for node in self.children {
// I used spritenode, but you can add as many nodes with color options as you like.
guard let snode = node as? SKSpriteNode else { continue }
snode.color = .blue
}
The inversion function would be a separate question I think :P but something like:
if snode.color == .black { node.color == .white }
But you could probably do this with RGB and math as well.