Das funktioniert für mich, um die Eingangslautstärke auf meinem MacBook Pro (Modell 2011) einzustellen. Es ist ein bisschen funky, ich musste versuchen, die Lautstärke des Master-Kanals einzustellen, dann jedes unabhängige Stereo-Kanal-Volume, bis ich einen gefunden habe, der funktioniert hat. Sehen Sie sich die Kommentare in meinem Code an. Ich vermute, der beste Weg zu sagen, ob Ihr Code funktioniert, ist, eine get/set-property-Kombination zu finden, die funktioniert, und dann etwas wie get/set (etwas anderes) zu tun Setter arbeitet.
Oh, und ich werde natürlich darauf hinweisen, dass ich nicht auf die Werte in der Adresse verlassen würde, die bei getProperty Calls gleich bleiben, wie ich hier mache. Es scheint zu funktionieren, aber es ist auf jeden Fall eine schlechte Übung, sich darauf zu verlassen, dass die Strukturwerte gleich sind, wenn Sie eine durch Verweis auf eine Funktion übergeben. Dies ist natürlich ein Beispielcode, bitte verzeih mir meine Faulheit. ;)
//
// main.c
// testInputVolumeSetter
//
#include <CoreFoundation/CoreFoundation.h>
#include <CoreAudio/CoreAudio.h>
OSStatus setDefaultInputDeviceVolume(Float32 toVolume);
int main(int argc, const char * argv[]) {
OSStatus err;
// Load the Sound system preference, select a default
// input device, set its volume to max. Now set
// breakpoints at each of these lines. As you step over
// them you'll see the input volume change in the Sound
// preference panel.
//
// On my MacBook Pro setting the channel[ 1 ] volume
// on the default microphone input device seems to do
// the trick. channel[ 0 ] reports that it works but
// seems to have no effect and the master channel is
// unsettable.
//
// I do not know how to tell which one will work so
// probably the best thing to do is write your code
// to call getProperty after you call setProperty to
// determine which channel(s) work.
err = setDefaultInputDeviceVolume(0.0);
err = setDefaultInputDeviceVolume(0.5);
err = setDefaultInputDeviceVolume(1.0);
}
// 0.0 == no volume, 1.0 == max volume
OSStatus setDefaultInputDeviceVolume(Float32 toVolume) {
AudioObjectPropertyAddress address;
AudioDeviceID deviceID;
OSStatus err;
UInt32 size;
UInt32 channels[ 2 ];
Float32 volume;
// get the default input device id
address.mSelector = kAudioHardwarePropertyDefaultInputDevice;
address.mScope = kAudioObjectPropertyScopeGlobal;
address.mElement = kAudioObjectPropertyElementMaster;
size = sizeof(deviceID);
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &address, 0, nil, &size, &deviceID);
// get the input device stereo channels
if (! err) {
address.mSelector = kAudioDevicePropertyPreferredChannelsForStereo;
address.mScope = kAudioDevicePropertyScopeInput;
address.mElement = kAudioObjectPropertyElementWildcard;
size = sizeof(channels);
err = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &channels);
}
// run some tests to see what channels might respond to volume changes
if (! err) {
Boolean hasProperty;
address.mSelector = kAudioDevicePropertyVolumeScalar;
address.mScope = kAudioDevicePropertyScopeInput;
// On my MacBook Pro using the default microphone input:
address.mElement = kAudioObjectPropertyElementMaster;
// returns false, no VolumeScalar property for the master channel
hasProperty = AudioObjectHasProperty(deviceID, &address);
address.mElement = channels[ 0 ];
// returns true, channel 0 has a VolumeScalar property
hasProperty = AudioObjectHasProperty(deviceID, &address);
address.mElement = channels[ 1 ];
// returns true, channel 1 has a VolumeScalar property
hasProperty = AudioObjectHasProperty(deviceID, &address);
}
// try to get the input volume
if (! err) {
address.mSelector = kAudioDevicePropertyVolumeScalar;
address.mScope = kAudioDevicePropertyScopeInput;
size = sizeof(volume);
address.mElement = kAudioObjectPropertyElementMaster;
// returns an error which we expect since it reported not having the property
err = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &volume);
size = sizeof(volume);
address.mElement = channels[ 0 ];
// returns noErr, but says the volume is always zero (weird)
err = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &volume);
size = sizeof(volume);
address.mElement = channels[ 1 ];
// returns noErr, but returns the correct volume!
err = AudioObjectGetPropertyData(deviceID, &address, 0, nil, &size, &volume);
}
// try to set the input volume
if (! err) {
address.mSelector = kAudioDevicePropertyVolumeScalar;
address.mScope = kAudioDevicePropertyScopeInput;
size = sizeof(volume);
if (toVolume < 0.0) volume = 0.0;
else if (toVolume > 1.0) volume = 1.0;
else volume = toVolume;
address.mElement = kAudioObjectPropertyElementMaster;
// returns an error which we expect since it reported not having the property
err = AudioObjectSetPropertyData(deviceID, &address, 0, nil, size, &volume);
address.mElement = channels[ 0 ];
// returns noErr, but doesn't affect my input gain
err = AudioObjectSetPropertyData(deviceID, &address, 0, nil, size, &volume);
address.mElement = channels[ 1 ];
// success! correctly sets the input device volume.
err = AudioObjectSetPropertyData(deviceID, &address, 0, nil, size, &volume);
}
return err;
}
EDIT als Antwort auf Ihre Frage: "Wie hast [I] Figur this out?"
Ich habe in den letzten fünf Jahren viel Zeit mit dem Audiocode von Apple verbracht und ich habe eine Intuition/einen Prozess entwickelt, wenn es darum geht, wo und wie nach Lösungen gesucht wird. Mein Geschäftspartner und ich haben die ursprünglichen iHeartRadio-Apps für das iPhone der ersten Generation und einige andere Geräte mitgeschrieben. Eine meiner Aufgaben in diesem Projekt war der Audioteil, speziell das Schreiben eines AAC Shoutcast Stream-Decoders/-Players für iOS. Es gab zu der Zeit keine Dokumente oder Open-Source-Beispiele, also war es eine Menge Versuch und Irrtum, und ich habe eine Menge gelernt.
Auf jeden Fall, als ich Ihre Frage las und sah die Bounty ich dachte, das war nur niedrig hängenden Frucht (d. H. Sie hatten nicht RTFM ;-). Ich habe ein paar Codezeilen geschrieben, um die Volume-Eigenschaft festzulegen, und als das nicht funktioniert habe, habe ich mich wirklich dafür interessiert.
Prozess weise vielleicht werden Sie dies nützlich finden:
Sobald ich wusste, dass es keine einfache Antwort war ich begann darüber nachzudenken, wie das Problem zu lösen. Ich wusste, dass das Sound System Preference können Sie die Eingangsverstärkung so eingestellt, dass ich durch Zerlegen es mit otool begonnen, um zu sehen, ob Apple-wurde die Verwendung von alten oder neuen Audio Toolbox Routinen machen (neu, wie es geschieht):
Versuchen Sie es mit:
otool -tV /System/Library/PreferencePanes/Sound.prefPane/Contents/MacOS/Sound | bbedit
dann für Audio
suchen, um zu sehen, welche Methoden aufgerufen werden (wenn Sie BBEdit nicht haben, die jeder Mac-Entwickler IMO sollte, werfen Sie es in einem anderen Text-Editor in eine Datei und öffnen).
Ich bin am vertrautesten mit den älteren, veralteten Audio Toolbox-Routinen (drei Jahre bis zur Veralterung in dieser Branche), also habe ich mir ein paar Technotes von Apple angeschaut.Sie haben eines, das zeigt, wie man das Standard-Eingabegerät erhält und seine Lautstärke mit den neuesten CoreAudio-Methoden einstellt, aber wie Sie zweifellos gesehen haben, funktioniert ihr Code nicht richtig (zumindest auf meinem MBP).
Sobald ich an diesen Punkt kam, fiel ich auf das Altbewährte zurück: Beginnen Sie mit der Suche nach Stichwörtern, die wahrscheinlich beteiligt sind (z. B. AudioObjectSetPropertyData
, kAudioDevicePropertyVolumeScalar
usw.).
Eine interessante Sache, die ich über CoreAudio- und mit dem Apple-Toolbox im Allgemeinen gefunden habe, ist, dass es einen gibt, viel von Open-Source-Code ist, wo die Menschen verschiedene Dinge (Tonnen Pastebins und Google Projekte etc.) versuchen . Wenn Sie bereit sind, einen Haufen Code zu durchforsten, werden Sie normalerweise entweder die Antwort finden oder sehr gute Ideen bekommen.
In meiner Suche waren die relevantesten Dinge, die ich fand, der Apple Technote, der zeigt, wie man das Standardeingabegerät erhält und die Haupteingabeverstärkung unter Verwendung der neuen Toolboxroutinen einstellt (obwohl es auf meiner Hardware nicht funktionierte), und Ich habe einen Code gefunden, der das Einstellen der Verstärkung nach Kanal auf einem Ausgabegerät anzeigt. Da Eingabegeräte mehrkanalig sein können, dachte ich mir, dass dies das nächste logische Mittel ist, es zu versuchen.
Ihre Frage ist wirklich gut, denn zumindest gibt es im Moment keine korrekte Dokumentation von Apple, die zeigt, wie Sie tun können, was Sie gefragt haben. Es ist auch albern, weil beide Kanäle berichten, dass sie die Lautstärke einstellen, aber nur eine von ihnen (das Eingangsmikrofon ist eine Monoquelle, also ist das nicht überraschend, aber ich denke über einen No-Op-Kanal und keine Dokumentation darüber nach eines Fehlers auf Apple).
Dies passiert ziemlich gleichmäßig, wenn Sie mit den neuesten Technologien von Apple beginnen. Sie können erstaunliche Dinge mit ihrer Toolbox tun und es bringt jedes andere Betriebssystem aus dem Wasser, mit dem ich gearbeitet habe, aber es dauert nicht lange, um ihre Dokumentation zu überholen, besonders wenn Sie versuchen, etwas Moderates zu machen.
Wenn Sie sich zum Beispiel dafür entscheiden, einen Kernel-Treiber zu schreiben, werden Sie die Dokumentation zu IOKit als unzureichend empfinden. Letztendlich müssen Sie online gehen und den Quellcode durchforsten, entweder die Projekte anderer Leute oder die OS X-Quelle oder beides, und bald werden Sie feststellen, dass die Quelle wirklich der beste Ort für Antworten ist (auch wenn StackOverflow ist ziemlich toll).
Danke für die Punkte und viel Glück mit Ihrem Projekt :)
Danke für die tolle Antwort. Aus Neugier und potentiellem zukünftigen Nutzen, wie kommt es, dass Sie entweder auf diese Lösung stießen oder das Wissen hatten, den Code zu schreiben? –
Stellt sich heraus, dass eine richtige Antwort nicht in einen Kommentar passt, also habe ich meine Antwort bearbeitet. Nochmals vielen Dank für die Prämie! – par
Tolle Beschreibung - Danke, dass du dir die Zeit genommen hast! –