Skip to content

Instantly share code, notes, and snippets.

@andreif
Last active August 29, 2015 14:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save andreif/018045f4a937213761f0 to your computer and use it in GitHub Desktop.
Save andreif/018045f4a937213761f0 to your computer and use it in GitHub Desktop.
# coding=utf-8
import ctypes
import ctypes.util
import sys
from coreaudio import (
AudioObjectPropertyAddress,
kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyScopeInput,
kAudioObjectPropertyElementMaster,
kAudioObjectSystemObject,
kAudioDevicePropertyStreamFormat,
AudioDeviceID,
AudioDeviceIOProc,
AudioDeviceIOProcID,
AudioDeviceCreateIOProcID,
AudioDeviceStart,
AudioDeviceStop,
AudioObjectGetPropertyData,
AudioObjectSetPropertyData,
AudioDeviceDestroyIOProcID,
AudioStreamBasicDescription,
)
@AudioDeviceIOProc
def proc_audio_input(inDevice, inNow, inInputData, inInputTime, outOutputData, inOutputTime, inClientData):
buf = inInputData[0].mBuffers[0]
s = ctypes.cast(buf.mData, ctypes.POINTER(ctypes.c_char))
sys.stdout.write(s[:buf.mDataByteSize])
return 0
thePropertyAddress = AudioObjectPropertyAddress(
kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster,
)
inDevice = AudioDeviceID()
thePropSize = ctypes.c_uint32(ctypes.sizeof(AudioDeviceID))
assert not AudioObjectGetPropertyData(
kAudioObjectSystemObject,
ctypes.byref(thePropertyAddress),
0,
None,
ctypes.byref(thePropSize),
ctypes.byref(inDevice)
)
inFormat = AudioStreamBasicDescription()
thePropSize = ctypes.c_uint32(ctypes.sizeof(AudioStreamBasicDescription))
thePropertyAddress = AudioObjectPropertyAddress(
kAudioDevicePropertyStreamFormat,
kAudioObjectPropertyScopeInput,
kAudioObjectPropertyElementMaster,
)
assert not AudioObjectGetPropertyData(
inDevice,
ctypes.byref(thePropertyAddress),
0,
None,
ctypes.byref(thePropSize),
ctypes.byref(inFormat)
)
if inFormat.mSampleRate != 44100.0:
inFormat.mSampleRate = 44100.0
assert not AudioObjectSetPropertyData(
inDevice,
ctypes.byref(thePropertyAddress),
0,
None,
ctypes.byref(thePropSize),
ctypes.byref(inFormat)
)
theIOProcID = AudioDeviceIOProcID()
assert not AudioDeviceCreateIOProcID(inDevice, proc_audio_input, None, ctypes.byref(theIOProcID))
assert not AudioDeviceStart(inDevice, theIOProcID)
try:
while 1:
pass
except (KeyboardInterrupt, SystemExit):
pass
finally:
assert not AudioDeviceStop(inDevice, theIOProcID)
assert not AudioDeviceDestroyIOProcID(inDevice, theIOProcID)
# coding=utf-8
import ctypes
import ctypes.util
CoreAudio = ctypes.cdll.LoadLibrary(ctypes.util.find_library('CoreAudio'))
bytes2int = lambda s: int(s.encode('hex'), 16)
OSStatus = ctypes.c_int32
kAudioObjectSystemObject = 1
kAudioHardwarePropertyDefaultInputDevice = bytes2int('dIn ')
kAudioHardwarePropertyDefaultOutputDevice = bytes2int('dOut')
kAudioDevicePropertyStreamFormat = bytes2int('sfmt')
kAudioObjectPropertyScopeGlobal = bytes2int('glob')
kAudioObjectPropertyScopeInput = bytes2int('inpt')
kAudioObjectPropertyScopeOutput = bytes2int('outp')
kAudioObjectPropertyScopePlayThrough = bytes2int('ptru')
kAudioObjectPropertyElementMaster = 0
AudioObjectPropertySelector = ctypes.c_uint32
AudioObjectPropertyScope = ctypes.c_uint32
AudioObjectPropertyElement = ctypes.c_uint32
AudioObjectID = ctypes.c_uint32
AudioDeviceID = AudioObjectID
class AudioObjectPropertyAddress(ctypes.Structure):
_fields_ = [
('mSelector', AudioObjectPropertySelector),
('mScope', AudioObjectPropertyScope),
('mElement', AudioObjectPropertyElement),
]
class AudioStreamBasicDescription(ctypes.Structure):
_fields_ = [
('mSampleRate', ctypes.c_double),
('mFormatID', ctypes.c_uint32),
('mFormatFlags', ctypes.c_uint32),
('mBytesPerPacket', ctypes.c_uint32),
('mFramesPerPacket', ctypes.c_uint32),
('mBytesPerFrame', ctypes.c_uint32),
('mChannelsPerFrame', ctypes.c_uint32),
('mBitsPerChannel', ctypes.c_uint32),
('mReserved', ctypes.c_uint32),
]
class AudioBuffer(ctypes.Structure):
_fields_ = [
('mNumberChannels', ctypes.c_uint32),
('mDataByteSize', ctypes.c_uint32),
('mData', ctypes.c_void_p),
]
class AudioBufferList(ctypes.Structure):
_fields_ = [
('mNumberBuffers', ctypes.c_uint32),
('mBuffers', AudioBuffer * 1),
]
# typedef OSStatus
# (*AudioDeviceIOProc)( AudioObjectID inDevice,
# const AudioTimeStamp* inNow,
# const AudioBufferList* inInputData,
# const AudioTimeStamp* inInputTime,
# AudioBufferList* outOutputData,
# const AudioTimeStamp* inOutputTime,
# void* inClientData);
AudioDeviceIOProc = ctypes.CFUNCTYPE(
OSStatus, # result type
AudioObjectID, # AudioObjectID inDevice,
ctypes.c_void_p, # const AudioTimeStamp* inNow,
ctypes.POINTER(AudioBufferList), # const AudioBufferList* inInputData,
ctypes.c_void_p, # const AudioTimeStamp* inInputTime,
ctypes.c_void_p, # AudioBufferList* outOutputData,
ctypes.c_void_p, # const AudioTimeStamp* inOutputTime,
ctypes.c_void_p, # void* inClientData
)
AudioDeviceIOProcID = AudioDeviceIOProc
def define(name, restype, argtypes):
f = getattr(CoreAudio, name)
f.restype = restype
f.argtypes = argtypes
return f
# extern OSStatus
# AudioObjectGetPropertyData( AudioObjectID inObjectID,
# const AudioObjectPropertyAddress* inAddress,
# UInt32 inQualifierDataSize,
# const void* inQualifierData,
# UInt32* ioDataSize,
# void* outData)
AudioObjectGetPropertyData = define('AudioObjectGetPropertyData', restype=OSStatus, argtypes=(
AudioObjectID, # inObjectID
ctypes.POINTER(AudioObjectPropertyAddress), # inAddress
ctypes.c_uint32, # inQualifierDataSize
ctypes.c_void_p, # inQualifierData
ctypes.POINTER(ctypes.c_uint32), # inDataSize
ctypes.c_void_p, # outData
))
# extern OSStatus
# AudioObjectSetPropertyData( AudioObjectID inObjectID,
# const AudioObjectPropertyAddress* inAddress,
# UInt32 inQualifierDataSize,
# const void* inQualifierData,
# UInt32 inDataSize,
# const void* inData)
AudioObjectSetPropertyData = define('AudioObjectSetPropertyData', restype=OSStatus, argtypes=(
AudioObjectID, # inObjectID
ctypes.POINTER(AudioObjectPropertyAddress), # inAddress
ctypes.c_uint32, # inQualifierDataSize
ctypes.c_void_p, # inQualifierData
ctypes.c_uint32, # inDataSize
ctypes.c_void_p, # outData
))
# extern OSStatus
# AudioDeviceCreateIOProcID( AudioObjectID inDevice,
# AudioDeviceIOProc inProc,
# void* inClientData,
# AudioDeviceIOProcID* outIOProcID)
AudioDeviceCreateIOProcID = define('AudioDeviceCreateIOProcID', restype=OSStatus, argtypes=(
AudioObjectID,
AudioDeviceIOProc,
ctypes.c_void_p,
ctypes.POINTER(AudioDeviceIOProcID),
))
# extern OSStatus
# AudioDeviceStart( AudioObjectID inDevice,
# AudioDeviceIOProcID inProcID)
AudioDeviceStart = define('AudioDeviceStart',
restype=OSStatus, argtypes=(AudioObjectID, AudioDeviceIOProcID))
AudioDeviceStop = define('AudioDeviceStop',
restype=OSStatus, argtypes=(AudioObjectID, AudioDeviceIOProcID))
AudioDeviceDestroyIOProcID = define('AudioDeviceDestroyIOProcID',
restype=OSStatus, argtypes=(AudioObjectID, AudioDeviceIOProcID))
#include <CoreAudio/CoreAudio.h>
static OSStatus recordAudioProc(
AudioDeviceID inDevice,
const AudioTimeStamp* inNow,
const AudioBufferList* inInputData,
const AudioTimeStamp* inInputTime,
AudioBufferList* outOutputData,
const AudioTimeStamp* inOutputTime,
void* inClientData)
{
unsigned byteCount = inInputData->mBuffers[0].mDataByteSize;
float *samples = (float*)inInputData->mBuffers[0].mData;
write(1, samples, byteCount);
return 0;
}
AudioDeviceID GetDefaultInputDevice()
{
AudioDeviceID inDevice = 0;
UInt32 theSize = sizeof(AudioDeviceID);
AudioObjectPropertyAddress theAddress = {
kAudioHardwarePropertyDefaultInputDevice,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster};
AudioObjectGetPropertyData(kAudioObjectSystemObject, &theAddress, 0, NULL, &theSize, &inDevice);
return inDevice;
}
AudioStreamBasicDescription GetDefaultInputDeviceFormat(AudioDeviceID inDevice)
{
AudioStreamBasicDescription inDeviceFormat;
UInt32 theSize = sizeof(AudioStreamBasicDescription);
AudioObjectPropertyAddress theAddress = {
kAudioDevicePropertyStreamFormat,
kAudioObjectPropertyScopeInput,
kAudioObjectPropertyElementMaster
};
AudioObjectGetPropertyData(inDevice, &theAddress, 0, NULL, &theSize, &inDeviceFormat);
return inDeviceFormat;
}
OSStatus SetDefaultInputDeviceFormat(AudioDeviceID inDevice, AudioStreamBasicDescription inDeviceFormat) {
UInt32 theSize = sizeof(AudioStreamBasicDescription);
AudioObjectPropertyAddress theAddress = {
kAudioDevicePropertyStreamFormat,
kAudioObjectPropertyScopeInput,
kAudioObjectPropertyElementMaster
};
return AudioObjectSetPropertyData(inDevice, &theAddress, 0, NULL, theSize, &inDeviceFormat);
}
int main(int argc, char *argv[])
{
AudioDeviceID inDevice = GetDefaultInputDevice();
AudioStreamBasicDescription inFormat = GetDefaultInputDeviceFormat(inDevice);
if (isatty(fileno(stdout))) {
printf("inDevice = %d \n", inDevice);
printf("inFormat->mSampleRate = %f \n", inFormat.mSampleRate);
printf("inFormat->mFormatID = %d \n", inFormat.mFormatID);
if (inFormat.mFormatID == kAudioFormatLinearPCM)
printf("inFormat->mFormatID == kAudioFormatLinearPCM \n");
printf("inFormat->mBytesPerPacket = %d \n", inFormat.mBytesPerPacket);
printf("inFormat->mFramesPerPacket = %d \n", inFormat.mFramesPerPacket);
printf("inFormat->mBytesPerFrame = %d \n", inFormat.mBytesPerFrame);
printf("inFormat->mChannelsPerFrame = %d \n", inFormat.mChannelsPerFrame);
printf("inFormat->mBitsPerChannel = %d \n", inFormat.mBitsPerChannel);
printf("inFormat->mFormatFlags = %d \n", inFormat.mFormatFlags);
return 0;
} else {
const float standard_rate = 44100.0;
if (inFormat.mSampleRate != standard_rate) {
inFormat.mSampleRate = standard_rate;
SetDefaultInputDeviceFormat(inDevice, inFormat);
}
}
// register the IOProc
AudioDeviceIOProcID theIOProcID = NULL;
AudioDeviceCreateIOProcID(inDevice, recordAudioProc, NULL, &theIOProcID);
// start IO
AudioDeviceStart(inDevice, theIOProcID);
if (argc > 1) {
sleep(strtoumax(argv[1], NULL, 10));
} else {
while (1) sleep(5);
}
// stop IO
AudioDeviceStop(inDevice, theIOProcID);
// unregister the IOProc
AudioDeviceDestroyIOProcID(inDevice, theIOProcID);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment