Commit d9c60823 authored by sletz's avatar sletz
Browse files

JackCoreAudioIOAdapter working


git-svn-id: http://subversion.jackaudio.org/jack/jack2/trunk/jackmp@2589 0c269be4-1314-0410-8aa9-9f06e86f4224
parent bba8d806
/*
Copyright (C) 2008 Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __JackFilters__
#define __JackFilters__
#include "jack.h"
namespace Jack
{
#define MAX_SIZE 64
struct JackFilter
{
jack_time_t fTable[MAX_SIZE];
JackFilter()
{
for (int i = 0; i < MAX_SIZE; i++)
fTable[i] = 0;
}
void AddValue(jack_time_t val)
{
memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
fTable[0] = val;
}
jack_time_t GetVal()
{
jack_time_t mean = 0;
for (int i = 0; i < MAX_SIZE; i++)
mean += fTable[i];
return mean / MAX_SIZE;
}
};
inline float Range(float min, float max, float val)
{
return (val < min) ? min : ((val > max) ? max : val);
}
}
#endif
......@@ -25,6 +25,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#include "JackError.h"
#include "JackResampler.h"
#include <samplerate.h>
#include <stdio.h>
namespace Jack
{
......
......@@ -115,9 +115,10 @@ extern "C"
return 1;
} else {
jack_log("Loading NetAudio Adapter");
// adapter = new Jack::JackNetIOAdapter(jack_client, new Jack::JackCoreAudioIOAdapter(2, 2, 512, 44100.f), 2, 2);
adapter = new Jack::JackCallbackNetIOAdapter(jack_client,
new Jack::JackPortAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2);
new Jack::JackCoreAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2);
//adapter = new Jack::JackCallbackNetIOAdapter(jack_client,
// new Jack::JackPortAudioIOAdapter(2, 2, jack_get_buffer_size(jack_client), jack_get_sample_rate(jack_client)), 2, 2);
assert(adapter);
if (adapter->Open() == 0) {
......
/*
Copyright (C) 2008 Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "JackResampler.h"
namespace Jack
{
JackResampler::JackResampler():fRatio(0)
{
int error;
fResampler = src_new(SRC_LINEAR, 1, &error);
if (error != 0)
jack_error("JackResampler::JackResampler err = %s", src_strerror(error));
fRingBuffer = jack_ringbuffer_create(sizeof(float) * DEFAULT_RB_SIZE);
}
JackResampler::~JackResampler()
{
src_delete(fResampler);
if (fRingBuffer)
jack_ringbuffer_free(fRingBuffer);
}
int JackResampler::Read(float* buffer, unsigned int frames)
{
size_t len = jack_ringbuffer_read_space(fRingBuffer);
jack_log("JackResampler::Read INPUT available = %ld", len / sizeof(float));
if (len < frames * sizeof(float)) {
jack_error("JackResampler::Read : producer too slow, skip frames = %d", frames);
//jack_ringbuffer_read(fRingBuffer, buffer, len);
return 0;
} else {
jack_ringbuffer_read(fRingBuffer, (char*)buffer, frames * sizeof(float));
return frames;
}
}
int JackResampler::Write(float* buffer, unsigned int frames)
{
size_t len = jack_ringbuffer_write_space(fRingBuffer);
jack_log("JackResampler::Write OUTPUT available = %ld", len / sizeof(float));
if (len < frames * sizeof(float)) {
jack_error("JackResampler::Write : consumer too slow, missing frames = %d", frames);
//jack_ringbuffer_write(fRingBuffer, buffer, len);
return 0;
} else {
jack_ringbuffer_write(fRingBuffer, (char*)buffer, frames * sizeof(float));
return frames;
}
}
int JackResampler::ReadResample(float* buffer, unsigned int frames)
{
jack_ringbuffer_data_t ring_buffer_data[2];
SRC_DATA src_data;
unsigned int frames_to_write = frames;
unsigned int written_frames = 0;
int res;
jack_ringbuffer_get_read_vector(fRingBuffer, ring_buffer_data);
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(float);
jack_log("OUPUT available = %ld", available_frames);
for (int j = 0; j < 2; j++) {
if (ring_buffer_data[j].len > 0) {
src_data.data_in = (float*)ring_buffer_data[j].buf;
src_data.data_out = &buffer[written_frames];
src_data.input_frames = ring_buffer_data[j].len / sizeof(float);
src_data.output_frames = frames_to_write;
src_data.end_of_input = 0;
src_data.src_ratio = fRatio;
res = src_process(fResampler, &src_data);
if (res != 0)
jack_error("JackPortAudioIOAdapter::Render err = %s", src_strerror(res));
frames_to_write -= src_data.output_frames_gen;
written_frames += src_data.output_frames_gen;
jack_log("OUTPUT : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen);
jack_ringbuffer_read_advance(fRingBuffer, src_data.input_frames_used * sizeof(float));
}
}
if (written_frames < frames)
jack_error("JackPortAudioIOAdapter::Render error written_frames = %ld", written_frames);
return written_frames;
}
int JackResampler::WriteResample(float* buffer, unsigned int frames)
{
jack_ringbuffer_data_t ring_buffer_data[2];
SRC_DATA src_data;
unsigned int frames_to_read = frames;
unsigned int read_frames = 0;
int res;
jack_ringbuffer_get_write_vector(fRingBuffer, ring_buffer_data);
unsigned int available_frames = (ring_buffer_data[0].len + ring_buffer_data[1].len) / sizeof(float);
jack_log("INPUT available = %ld", available_frames);
for (int j = 0; j < 2; j++) {
if (ring_buffer_data[j].len > 0) {
src_data.data_in = &buffer[read_frames];
src_data.data_out = (float*)ring_buffer_data[j].buf;
src_data.input_frames = frames_to_read;
src_data.output_frames = (ring_buffer_data[j].len / sizeof(float));
src_data.end_of_input = 0;
src_data.src_ratio = fRatio;
res = src_process(fResampler, &src_data);
if (res != 0)
jack_error("JackPortAudioIOAdapter::Render err = %s", src_strerror(res));
frames_to_read -= src_data.input_frames_used;
read_frames += src_data.input_frames_used;
jack_log("INPUT : j = %d input_frames_used = %ld output_frames_gen = %ld", j, src_data.input_frames_used, src_data.output_frames_gen);
jack_ringbuffer_write_advance(fRingBuffer, src_data.output_frames_gen * sizeof(float));
}
}
if (read_frames < frames)
jack_error("JackPortAudioIOAdapter::Render error read_frames = %ld", read_frames);
return read_frames;
}
}
/*
Copyright (C) 2008 Grame
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __JackResampler__
#define __JackResampler__
#include "ringbuffer.h"
#include "JackError.h"
#include <samplerate.h>
namespace Jack
{
#define DEFAULT_RB_SIZE 16384
class JackResampler
{
protected:
SRC_STATE* fResampler;
jack_ringbuffer_t* fRingBuffer;
double fRatio;
public:
JackResampler();
virtual ~JackResampler();
int ReadResample(float* buffer, unsigned int frames);
int WriteResample(float* buffer, unsigned int frames);
int Read(float* buffer, unsigned int frames);
int Write(float* buffer, unsigned int frames);
void SetRatio(double ratio)
{
fRatio = ratio;
}
double GetRatio()
{
return fRatio;
}
};
}
#endif
......@@ -194,9 +194,9 @@ def build(bld):
create_jack_process_obj(bld, 'netmanager', 'JackNetManager.cpp', serverlib)
#create_jack_process_obj(bld, 'netioadapter', 'JackNetIOAdapter.cpp ../macosx/JackCoreAudioIOAdapter.cpp', serverlib)
process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../macosx/JackCoreAudioIOAdapter.cpp', serverlib)
#process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../windows/JackPortAudioIOAdapter.cpp', serverlib)
process = create_jack_process_obj(bld, 'netioadapter', 'JackResampler.cpp JackIOAdapter.cpp JackNetIOAdapter.cpp JackCallbackNetIOAdapter.cpp ../windows/JackPortAudioIOAdapter.cpp', serverlib)
process.env.append_value("LINKFLAGS", "-lsamplerate")
if bld.env()['IS_MACOSX']:
process.env.append_value("LINKFLAGS", "../macosx/libportaudio.a -framework CoreAudio -framework AudioUnit -framework AudioToolbox -framework CoreServices")
......
......@@ -224,7 +224,7 @@ OSStatus JackCoreAudioDriver::SRNotificationCallback(AudioDeviceID inDevice,
switch (inPropertyID) {
case kAudioDevicePropertyNominalSampleRate: {
jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate ");
jack_log("JackCoreAudioDriver::SRNotificationCallback kAudioDevicePropertyNominalSampleRate");
driver->fState = true;
break;
}
......
This diff is collapsed.
......@@ -21,6 +21,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define __JackCoreAudioIOAdapter__
#include "JackIOAdapter.h"
#include "JackFilters.h"
#include "jack.h"
#include <AudioToolbox/AudioConverter.h>
#include <CoreAudio/CoreAudio.h>
......@@ -29,12 +30,11 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
namespace Jack
{
typedef UInt8 CAAudioHardwareDeviceSectionID;
#define kAudioDeviceSectionInput ((CAAudioHardwareDeviceSectionID)0x01)
#define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00)
#define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00)
#define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF)
typedef UInt8 CAAudioHardwareDeviceSectionID;
#define kAudioDeviceSectionInput ((CAAudioHardwareDeviceSectionID)0x01)
#define kAudioDeviceSectionOutput ((CAAudioHardwareDeviceSectionID)0x00)
#define kAudioDeviceSectionGlobal ((CAAudioHardwareDeviceSectionID)0x00)
#define kAudioDeviceSectionWildcard ((CAAudioHardwareDeviceSectionID)0xFF)
class JackCoreAudioIOAdapter : public JackIOAdapterInterface
{
......@@ -42,24 +42,31 @@ typedef UInt8 CAAudioHardwareDeviceSectionID;
private:
AudioUnit fAUHAL;
AudioBufferList* fInputData;
JackFilter fProducerFilter;
JackFilter fConsumerFilter;
AudioDeviceID fDeviceID;
bool fState;
AudioUnitRenderActionFlags* fActionFags;
AudioTimeStamp* fCurrentTime;
static OSStatus Render(void *inRefCon,
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData);
AudioUnitRenderActionFlags *ioActionFlags,
const AudioTimeStamp *inTimeStamp,
UInt32 inBusNumber,
UInt32 inNumberFrames,
AudioBufferList *ioData);
static OSStatus SRNotificationCallback(AudioDeviceID inDevice,
UInt32 inChannel,
Boolean isInput,
AudioDevicePropertyID inPropertyID,
void* inClientData);
OSStatus GetDeviceIDFromUID(const char* UID, AudioDeviceID* id);
OSStatus GetDefaultDevice(AudioDeviceID* id);
OSStatus GetDefaultInputDevice(AudioDeviceID* id);
OSStatus GetDefaultOutputDevice(AudioDeviceID* id);
OSStatus GetDeviceNameFromID(AudioDeviceID id, char* name);
OSStatus GetTotalChannels(AudioDeviceID device, int* channelCount, bool isInput);
// Setup
......@@ -75,14 +82,26 @@ typedef UInt8 CAAudioHardwareDeviceSectionID;
int& in_nChannels,
int& out_nChannels,
bool strict);
int OpenAUHAL(bool capturing,
bool playing,
int inchannels,
int outchannels,
int in_nChannels,
int out_nChannels,
jack_nframes_t nframes,
jack_nframes_t samplerate,
bool strict);
int SetupBufferSizeAndSampleRate(jack_nframes_t nframes, jack_nframes_t samplerate);
int SetupBuffers(int inchannels, int outchannels);
void DisposeBuffers();
void CloseAUHAL();
public:
JackCoreAudioIOAdapter(int input, int output, int buffer_size, float sample_rate)
:JackIOAdapterInterface(input, output, buffer_size, sample_rate)
:JackIOAdapterInterface(input, output, buffer_size, sample_rate),fInputData(0),fState(false)
{}
~JackCoreAudioIOAdapter()
{}
......
......@@ -49,24 +49,20 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
if (!adapter->fRunning) {
adapter->fRunning = true;
paBuffer = (float**)inputBuffer;
float buffer[framesPerBuffer];
for (int i = 0; i < adapter->fCaptureChannels; i++) {
buffer = static_cast<float*>(paBuffer[i]);
adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
adapter->fCaptureRingBuffer[i].Read(buffer, framesPerBuffer);
adapter->fCaptureRingBuffer[i].Read(buffer, inNumberFrames);
adapter->fCaptureRingBuffer[i].Read(buffer, inNumberFrames);
adapter->fCaptureRingBuffer[i].Read(buffer, inNumberFrames);
}
paBuffer = (float**)outputBuffer;
for (int i = 0; i < adapter->fPlaybackChannels; i++) {
buffer = static_cast<float*>(paBuffer[i]);
adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
adapter->fPlaybackRingBuffer[i].Write(buffer, framesPerBuffer);
adapter->fPlaybackRingBuffer[i].Write(buffer, inNumberFrames);
adapter->fPlaybackRingBuffer[i].Write(buffer, inNumberFrames);
adapter->fPlaybackRingBuffer[i].Write(buffer, inNumberFrames);
}
}
}
/*
double src_ratio_output = double(adapter->fCurCallbackTime - adapter->fLastCallbackTime) / double(adapter->fDeltaTime);
double src_ratio_input = double(adapter->fDeltaTime) / double(adapter->fCurCallbackTime - adapter->fLastCallbackTime);
......@@ -91,16 +87,16 @@ int JackPortAudioIOAdapter::Render(const void* inputBuffer, void* outputBuffer,
for (int i = 0; i < adapter->fCaptureChannels; i++) {
buffer = (float*)paBuffer[i];
adapter->fCaptureRingBuffer[i].SetRatio(src_ratio_input);
//int len = adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer);
int len = adapter->fCaptureRingBuffer[i].Write(buffer, framesPerBuffer);
//adapter->fCaptureRingBuffer[i].WriteResample(buffer, framesPerBuffer);
adapter->fCaptureRingBuffer[i].Write(buffer, framesPerBuffer);
}
paBuffer = (float**)outputBuffer;
for (int i = 0; i < adapter->fPlaybackChannels; i++) {
buffer = (float*)paBuffer[i];
adapter->fPlaybackRingBuffer[i].SetRatio(src_ratio_output);
//int len = adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer);
int len = adapter->fPlaybackRingBuffer[i].Read(buffer, framesPerBuffer);
//adapter->fPlaybackRingBuffer[i].ReadResample(buffer, framesPerBuffer);
adapter->fPlaybackRingBuffer[i].Read(buffer, framesPerBuffer);
}
return paContinue;
......
......@@ -21,40 +21,13 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#define __JackPortAudioIOAdapter__
#include "JackIOAdapter.h"
#include "JackFilters.h"
#include "portaudio.h"
namespace Jack
{
#define MAX_SIZE 64
struct Filter {
jack_time_t fTable[MAX_SIZE];
Filter()
{
for (int i = 0; i < MAX_SIZE; i++)
fTable[i] = 0;
}
void AddValue(jack_time_t val)
{
memcpy(&fTable[1], &fTable[0], sizeof(jack_time_t) * (MAX_SIZE - 1));
fTable[0] = val;
}
jack_time_t GetVal()
{
jack_time_t mean = 0;
for (int i = 0; i < MAX_SIZE; i++)
mean += fTable[i];
return mean / MAX_SIZE;
}
};
class JackPortAudioIOAdapter : public JackIOAdapterInterface
class JackPortAudioIOAdapter : public JackIOAdapterInterface
{
private:
......@@ -63,8 +36,8 @@ namespace Jack
PaDeviceIndex fInputDevice;
PaDeviceIndex fOutputDevice;
Filter fProducerFilter;
Filter fConsumerFilter;
JackFilter fProducerFilter;
JackFilter fConsumerFilter;
static int Render(const void* inputBuffer, void* outputBuffer,
unsigned long framesPerBuffer,
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment