Re: Bug in saving user presets [Solved]
Re: Bug in saving user presets [Solved]
- Subject: Re: Bug in saving user presets [Solved]
- From: Robert Abernathy <email@hidden>
- Date: Tue, 31 Jan 2006 01:00:56 +0000
Will do.
Thanks for the tip. I think I can get the test case to just a few
lines of code. I'd guess it has to do with the embedded structs in
the loop. The int <-> float trickery may contribute too.
Rob
On 27 Jan 2006, at 22:45, Doug Wyatt wrote:
So it sounds like the autovectorization option in the compiler is
misbehaving. I'd suggest filing a bug against the compiler. They'll
want a complete "compiler test case", which means giving them
preprocessed source code. I usually do this by grabbing the
compiler command line out of the Xcode build log and modifying it
as follows:
remove "-x c++"
remove "-o <filename>"
add "-E"
add "> preprocessed.c"
Then execute the modified command line in Terminal.
Doug
On Jan 27, 2006, at 5:00, Robert Abernathy wrote:
The problem turns out to be in AUElement. If the Auto-
vectorization flag is set in the compiler, SaveState and
RestoreState shift the order of the preset values. This may not
show in AU's with a small number of presets.
Since the audio portions of the AU are all done using the
Accelerate framework, this flag isn't getting me anything anyway.
So, my problem is solved. But, it is a bit weird and a major pain
to track down.
Rob
On 25 Jan 2006, at 21:39, Robert Abernathy wrote:
I'm tracking down a bug in user presets in an AU I'm working on.
I've tracked it down to being in AUBase::SaveState or
AUElement::SaveState.
The parameter data is being gathered correctly in
AUElement::SaveState. If I print it here as it is being pulled
from mParameters or mIndexedParameters, it is correct.
If I take the, the dictionary that is built in AUBase::SaveState
and print it out immediately after the parameter data is added, I
can see that the data is wrong at this point. (See code below,
the function TestState is where the data is checked. It mimics
the read data in AUElement::RestoreState to do the dictionary/
data read.)
The parameter data is offset by two indices. As the parameters
are read back in AUElement::PrintState, the zeroth and first
elements are garbage (close to zero). The 2nd entry contains the
value of the zeroth parameter. The 3rd entry contains the value
of the first parameter and so forth, up to the 90th entry
containing the value of the 88th parameter. The 89th and 90th
parameters are missing.
If I print the data out as it is being read back in
AUElement::RestoreState, the pattern above is the same. Shifted
off by two with the first two entries garbage.
The code I used for testing is below.
Any help would be much appreciated as I'm kinda stuck here.
Thanks,
Rob
Code
below---------------------------------------------------------------
---------------
ComponentResult AUBase::SaveState( CFPropertyListRef * outData)
{
ComponentDescription desc;
OSStatus result = GetComponentInfo((Component)
GetComponentInstance(), &desc, NULL, NULL, NULL);
if (result) return result;
CFMutableDictionaryRef dict = CFDictionaryCreateMutable (NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
// first step -> save the version to the data ref
SInt32 value = kCurrentSavedStateVersion;
AddNumToDictionary (dict, kVersionString, value);
// second step -> save the component type, subtype, manu to the
data ref
value = desc.componentType;
AddNumToDictionary (dict, kTypeString, value);
value = desc.componentSubType;
AddNumToDictionary (dict, kSubtypeString, value);
value = desc.componentManufacturer;
AddNumToDictionary (dict, kManufacturerString, value);
// fourth step -> save the state of all parameters on all scopes
and elements
CFMutableDataRef data = CFDataCreateMutable(NULL, 0);
for (AudioUnitScope iscope = 0; iscope < 4; ++iscope) {
if (iscope == kAudioUnitScope_Group)
continue;
AUScope &scope = GetScope(iscope);
AudioUnitElement nElems = scope.GetNumberOfElements();
for (AudioUnitElement ielem = 0; ielem < nElems; ++ielem) {
AUElement *element = scope.GetElement(ielem);
UInt32 nparams = element->GetNumberOfParameters();
if (nparams > 0) {
struct {
UInt32 scope;
UInt32 element;
} hdr;
hdr.scope = EndianU32_NtoB(iscope);
hdr.element = EndianU32_NtoB(ielem);
CFDataAppendBytes(data, (UInt8 *)&hdr, sizeof(hdr));
element->SaveState(data);
}
}
}
// save all this in the data section of the dictionary
CFDictionarySetValue(dict, kDataString, data);
CFRelease (data);
TestState(dict); // my added function to print out the data
//OK - now we're going to do some properties
//save the preset name...
CFDictionarySetValue (dict, kNameString,
mCurrentPreset.presetName);
// Does the unit support the RenderQuality property - if so, save
it...
value = 0;
result = DispatchGetProperty (kAudioUnitProperty_RenderQuality,
kAudioUnitScope_Global,
0,
&value);
if (result == noErr) {
AddNumToDictionary (dict, kRenderQualityString, value);
}
// Does the unit support the CPULoad Quality property - if so,
save it...
Float32 cpuLoad;
result = DispatchGetProperty (kAudioUnitProperty_CPULoad,
kAudioUnitScope_Global,
0,
&cpuLoad);
if (result == noErr) {
CFNumberRef num = CFNumberCreate (NULL, kCFNumberFloatType,
&cpuLoad);
CFDictionarySetValue (dict, kCPULoadString, num);
CFRelease (num);
}
// Do we have any element names for any of our scopes?
// first check to see if we have any names...
bool foundName = false;
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
foundName = GetScope (i).HasElementWithName();
if (foundName)
break;
}
// OK - we found a name away we go...
if (foundName) {
CFMutableDictionaryRef nameDict = CFDictionaryCreateMutable
(NULL, 0,
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks);
for (AudioUnitScope i = 0; i < kNumScopes; ++i) {
GetScope (i).AddElementNamesToDict (nameDict);
}
CFDictionarySetValue (dict, kElementNameString, nameDict);
CFRelease (nameDict);
}
// we're done!!!
*outData = dict;
return noErr;
}
// -------------------------------------
// little function to test the data in the preset
void AUBase::TestState(CFMutableDictionaryRef dict) {
std::cout << "AUBase::TestState() . Count " <<
CFDictionaryGetCount(dict) << "\n";
CFDataRef data = reinterpret_cast<CFDataRef>
(CFDictionaryGetValue (dict, kDataString));
if (data != NULL)
{
const UInt8 *p, *pend;
p = CFDataGetBytePtr(data);
pend = p + CFDataGetLength(data);
// we have a zero length data, which may just mean there were
no parameters to save!
// if (p >= pend) return noErr;
while (p < pend) {
struct {
UInt32 scope;
UInt32 element;
} hdr;
hdr.scope = EndianU32_BtoN(*(UInt32 *)p); p += sizeof(UInt32);
hdr.element = EndianU32_BtoN(*(UInt32 *)p); p += sizeof(UInt32);
AUScope &scope = GetScope(hdr.scope);
AUElement *element = scope.GetElement(hdr.element);
// $$$ order of operations issue: what if the element does
not yet exist?
// then we just break out of the loop
if (!element)
break;
p = element->PrintState(p);
}
}
}
// My added routine
// It mimicks AUElement::RestoreState
const UInt8 * AUElement::PrintState(const UInt8 *state)
{
const UInt8 *p = state;
UInt32 nparams = EndianU32_BtoN(*(UInt32 *)p);
std::cout << "Print state ... NParams = " << nparams << "\n";
p += sizeof(UInt32);
for (UInt32 i = 0; i < nparams; ++i) {
struct {
UInt32 paramID;
Float32 value;
} entry;
entry.paramID = EndianU32_BtoN(*(UInt32 *)p);
p += sizeof(UInt32);
UInt32 temp = EndianU32_BtoN(*(UInt32 *)p);
entry.value = *(Float32 *)&temp;
p += sizeof(Float32);
std::cout << "Print - Element: id = " << entry.paramID << "
value = " << entry.value << "\n";
}
return p;
}
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40musicunfolding.com
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40apple.com
This email sent to email@hidden
--
Doug Wyatt
Core Audio, Apple
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40musicunfolding.com
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Coreaudio-api mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden