The Problem
I am trying to get the new AUParameterTree and AUParameter's mechanism working in my Audio Unit V3 test project. The problem is that when I gain a reference to it from the Host App and change its value, the Audio Unit extension's parameter doesn't appear to change.
Here is my approach.
I'm using the new Audio Unit V3 API. I've created an AUParameter in my AUAudioUnit's initWithComponentDescription:
Creating the Parameter
AUParameter *param1 = [AUParameterTree createParameterWithIdentifier:#"frequency"
name:#"Frequency"
address:frequencyAddress
min:500
max:5000
unit:kAudioUnitParameterUnit_Hertz
unitName:nil
flags:0
valueStrings:nil
dependentParameters:nil];
Set a default value..
param1.value = 0.5;
some of the arguments to the Parameter constructor come from...
Some State
I have defined the address as a global constants:
const AudioUnitParameterID frequencyAddress = 0;
And a local variable for an AUValue:
AUValue frequency = 1;
Keep in mind at this point I'm just following the three example projects that use Audio Unit V3 on the entire internet. I find it difficult to piece together how this entire AU parameter dance should go only from reading the docs.
Rendering with the parameter
now when it comes to using the AUValue associated with the AUParameter "param1", (I assume thats how it works?)..
I am then capturing this AUValue ( the local variable which I'm unclear on how it is associated with the actual AUParameter ) .. in my Audio Unit rendering block:
- (AUInternalRenderBlock)internalRenderBlock {
AUValue * param1Capture = &frequency;
return ^AUAudioUnitStatus(AudioUnitRenderActionFlags *actionFlags, const AudioTimeStamp *timestamp, AVAudioFrameCount frameCount, NSInteger outputBusNumber, AudioBufferList *outputData, const AURenderEvent *realtimeEventListHead, AURenderPullInputBlock pullInputBlock) {
// use parameter value
someValue = *param1Capture;
// more dsp stuff..
Controlling Parameter from Host App
This is where the problem arises.
I declare a local reference to an AUParameter:
#interface ViewController (){
AudioEngine *_audioEngine;
AUParameter * _param1;
}
and when my Audio Engine class instantiates my AUAudioUnit it passes it to me:
[_audioEngine setupAUWithComponentDescription:desc andCompletion:^(AUAudioUnit * unit){
_param1 = [unit.parameterTree valueForKey:#"frequency"];
}];
no effect?
Now when I say:
[_param1 setValue: 1000];
The captured AUValue in my rendering block remains the same!
I've either overlooked a bug, a mindless type (I may have introduced a type in this write up of my problem so keep that in mind), or I have fundamentally misunderstood this mechanism.
If I need to provide more context for this problem I can easily push the project to Github.
Thanks in advance.
The problem turned out to have nothing to do with Core Audio and everything to do with a basic language level mistake.
frequency was declared at a file level scope like this:
AUValue frequency = 1;
#implementation MyAudioUnit
#end
My understanding is that frequency is now bound to file scope and not instance scope. Therefore repeated setting of it on different instances was simply overwriting the previous value. Hence, the last assignment was the frequency which would be rendered.
Related
so I was wondering if there was a way to reference different objects on stage with he same method to save repeating lots of lines of code. This is what I have right now
function bossKilled(i:Number):Void {
trace("Boss Killed!");
kills ++;
_root.bossDeath.gotoAndPlay(2);
_root["pirate"+i+"Active"] = false; //name of variable would be pirate1Active
_root["pirate"+(i+1)+"Active"] = true; //name of variable would be pirate2Active
bossDeath._x = _root["pirate"+i+"Active"]._x;
bossDeath._y = _root["pirate"+i+"Active"]._y; }
However, this reference does not actually affect the variables. I was wondering if this was possible, and if so, what am I doing wrong?
Thanks.
Not sure what you try to achieve ... pirate1Active is a BOOL. A BOOL has no _x or _y property (nor any other).
If you are not sure where to find your objects in the object tree, you can use the debugger or add some traces on the MCs timeline, like trace (_parent);
Consider switching to AS3, it is much more object oriented and has better tools support.
I'm trying to understand IOKit and how it allows me to access serial ports in a Swift program.
The class I'm manipulating at the moment is as follows:
import Foundation
import Cocoa
import IOKit.serial.IOSerialKeys
class Serial {
init() {
}
#IBOutlet var serialListPullDown : NSPopUpButton!
func refreshSerialList(defaultprompt: String) {
// remove everything from the pull down list
serialListPullDown?.removeAllItems()
// ask for all the serial ports
IOServiceGetMatchingServices(kIOMasterPortDefault, IOServiceMatching(kIOSerialBSDServiceValue), io_iterator_t)
}
}
Based on what I've read I think I've setup IOServiceMatchingServices correctly but I'm getting several errors such as "Expected member name or constructor call after type name" and "'o_iterator_t.Type' is not convertible to 'UnsafeMutualPointer'"
What does this mean?
A few different issues going on in there -- let's get your imports squared away first. It looks like you need these two:
import IOKit
import IOKit.serial
For the parameters, it'll be easier to see what we're working with if we define them as local variables, like so:
// this one's easy, just grabbing a constant from IOKit.serial
let masterPort: mach_port_t = kIOMasterPortDefault
// here we get back an Unmanaged<CFMutableDictionary> and need to convert it to
// a CFDictionary using takeRetainedValue()
let classesToMatch: CFDictionary = IOServiceMatching(kIOSerialBSDServiceValue).takeRetainedValue()
// the iterator that will contain the results of IOServiceGetMatchingServices
var matchingServices: io_iterator_t = 0
And lastly, you call the method:
// note that the last parameter is an UnsafeMutablePointer<io_iterator_t>
// so we need to prefix matchingServices with an ampersand (&)
let kernResult = IOServiceGetMatchingServices(masterPort, classesToMatch, &matchingServices)
if kernResult == KERN_SUCCESS {
// success
} else {
// error
}
This feels pretty near the edge of what Swift can handle right now -- definitely read these two pages well before going further:
Interacting with C APIs (Pointers section)
Working with Cocoa Data Types (Unmanaged Objects section)
Lastly, make sure you can get into the converted Swift declarations for the IOKit framework. There are a lot of useful comments and you'll be able to see which parameters and return values are unmanaged or pointers (since I don't think this framework's official documentation has been updated yet).
I'm doing an asynchronous read from a USB printer. The read works correctly. My trouble is updating a NSTextField from within the callback.
-(IBAction)printTest:(id)sender
{
// Setup... then:
NSLog(#"starting async read: %#", _printerOutput);
NSLog(#"_printerOutput pointer = %p", _printerOutput);
result = (*interface)->ReadPipeAsyncTO(interface,
1,
readBuffer,
numBytesRead,
500,
1000,
USBDeviceReadCompletionCallback,
&(_printerOutput)
);
The callback is defined as:
void USBDeviceReadCompletionCallback(void *refCon, IOReturn result, void *messageArg)
{
NSTextField *printerOutput = (__bridge NSTextField *) messageArg;
NSLog(#"_printerOutput pointer = %p", printerOutput);
}
The pointer loses its value when inside of the callback.
starting async read: <NSTextField: 0x10221dc60>
_printerOutput pointer = 0x10221dc60
_printerOutput pointer = 0x0
I've looked in many places trying to mimic different ways to pass in the pointer. There can be only one correct way. :)
Another variation on the theme: (__bridge void *)(_printerOutput). This doesn't work, either.
I understand that the callback is of type IOAsyncCallback1.
Other URLs of note:
http://www.google.com/search?client=safari&rls=en&q=another+usb+notification+example&ie=UTF-8&oe=UTF-8 and updating UI from a C function in a thread
I presume _printerOutput is an NSTextField*?
First, is there a particular reason why are you passing an NSTextField** into the callback? (Note the ampersand in the last argument you're passing to ReadPipeAsyncTO.)
Second, I'd avoid ARC with sensitive code, just as a precaution.
Third, from what I see, last argument of ReadPipeAsyncTO is called refcon. Is it a coincidence that callback's first argument is called refCon? Note you're trying to get a text field from messageArg, not refCon.
To extend on my third point…
ReadPipeAsyncTO has an argument called refcon. This is the last argument.
Please pass _printerOutput there. Not a pointer to _printerOutput (do not pass &(_printerOutput)) -- _printerOutput is already a pointer.
Now finally. Look at the first argument of the callback. It's called refcon. In fact -- let's see what Apple docs say about this callback:
refcon
The refcon passed into the original I/O request
My conclusion is that your code should read:
void USBDeviceReadCompletionCallback(void *refCon, IOReturn result, void *messageArg)
{
NSTextField *printerOutput = (__bridge NSTextField *) refCon; // <=== the change is here
NSLog(#"_printerOutput pointer = %p", printerOutput);
}
Can you, please, try this out? I get a feeling that you didn't try this.
Small but possibly important digression: Were it some other object, and if you didn't use ARC, I'd suggest retaining the _printerOutput variable when passing it into ReadPipeAsyncTO, and releasing it in the callback.
But, since the text field should, presumably, have the lifetime of the application, there is probably no need to do so.
ARC probably loses track of the need for the object behind the pointer to exist once it's passed into C code, but it doesn't matter, since the pointer is still stored in the printerOutput property. Besides, once a pointer is in C code, nothing can just "follow it around" and "reset it".
Confusion when it comes to understanding and explaining the concepts is precisely why I said "avoid ARC with sensitive code". :-)
I'm using Actionscript 2.0 for a mobile phone and can't get my head around Events.
I'm creating a class object with all my code and using a group of functions (all as direct 1st level children of the class). There's one function that creates a Movieclip with a square on it and sets the onPress event to another function called hit:
public function draw1Sqr(sName:String,pTL:Object,sSide:Number,rgb:Number){
// create a movie clip for the Sqr
var Sqr:MovieClip=this.canvas_mc.createEmptyMovieClip(sName,this.canvas_mc.getNextHighestDepth());
// draw square
Sqr.beginFill(rgb);
//etc ...more lines
//setup properties (these are accessible in the event)
Sqr.sSide=sSide;
Sqr.sName=sName;
//setup event
Sqr.onPress = hit; // this syntax seems to lead to 'this' within
// the handler function to be Sqr (movieclip)
//Sqr.onPress = Delegate.create(this, hit);
//I've read a lot about Delegate but it seems to make things harder for me.
}
Then in my event handler, I just cannot get the scope right...
public function hit(){
for (var x in this){
trace(x + " == " + this[x]);
}
//output results
//onPress == [type Function]
//sName == bSqr_7_4
//sSide == 20
trace(eval(this["._parent"])); //undefined
trace(eval(this["._x"])); //undefined
}
For some reason, although the scope is set to the calling object (Sqr, a Movieclip) and I can access properties I defined, I can't use the 'native' properties of a Movieclip object.
Any suggestions on how I can access the _x, _y and other properties of the Movieclip object that is pressed.
Use the array accessor or the dot accessor, but not both. For example:
trace(this._parent); // OR
trace(this["_parent"]);
As for the results of your iteration, I recall AS2 being screwy on this front. IIRC only dynamic properties are returned when looping with for ... in. This prevents Objects (which often serve as hash maps) from including their native properties when all you want are the key/value pairs you set yourself.
Also - the eval() function can be easily overused. Unless you absolutely must execute a String of AS2 that you don't have at compile-time I would recommend avoiding it. Happy coding!
Does somebody know if is it possible somehow to create a custom NSAnimationCurve so that it could be used with NSViewAnimation objects but was different from standard linear, EaseIn/Out?
Actually a have already found an answer to my question. I've created a delegate for my animation NSViewAnimation object and set it using:
[animationObject setDelegate: delegateObject];
Then in header file for my delagateObject I set it to use "NSAnimationDelegate" protocol typing the following string:
#interface delegateObject : NSObject <NSAnimationDelegate> {
After that I create a method
-(float)animation:(NSAnimation *)animation valueForProgress:(NSAnimationProgress)progress;
This should be a function that describes your custom animation curve. So it takes the progress of animation as value from 0.0 to 1.0 and converts it to new value from 0.0 to 1.0 according to function which you use.
I used in my code the following function:
-(float)animation:(NSAnimation *)animation valueForProgress:(NSAnimationProgress)progress {
float value = -1/(20*(progress+0.047)) +1.045;
return value;
}
It is something like EaseOut but working properly without need to change Start and End KeyFrames and with much more significant difference of speed at the beginning and end of animation.