MIDI: Fix Audio Unit player in several ways
Improve rendering functions of Audio Unit player, and also fix looping for the Audio Unit player, and any other possible future players which use blocked decoding with timestamped events. Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
parent
8cfddb875c
commit
40d9574015
3 changed files with 33 additions and 21 deletions
|
@ -37,6 +37,7 @@
|
|||
83B06722180D70FE008E3612 /* MIDIDecoder.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83B06721180D70FE008E3612 /* MIDIDecoder.mm */; };
|
||||
83C35702180EDB74007E9DF0 /* MIDIContainer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83C35700180EDB74007E9DF0 /* MIDIContainer.mm */; };
|
||||
83C35705180EDD1C007E9DF0 /* MIDIMetadataReader.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83C35703180EDD1C007E9DF0 /* MIDIMetadataReader.mm */; };
|
||||
83E83F7B2D9654470054365C /* Accelerate.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 83E83F7A2D9654470054365C /* Accelerate.framework */; };
|
||||
83E973471C4378880007F413 /* AUPlayer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 83E973451C4378880007F413 /* AUPlayer.mm */; };
|
||||
83EA54232A6A6CF400CD0580 /* libbass_mpc.dylib in CopyFiles */ = {isa = PBXBuildFile; fileRef = 83EA54212A6A6CE200CD0580 /* libbass_mpc.dylib */; settings = {ATTRIBUTES = (CodeSignOnCopy, ); }; };
|
||||
/* End PBXBuildFile section */
|
||||
|
@ -155,6 +156,7 @@
|
|||
83C35701180EDB74007E9DF0 /* MIDIContainer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIContainer.h; sourceTree = "<group>"; };
|
||||
83C35703180EDD1C007E9DF0 /* MIDIMetadataReader.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = MIDIMetadataReader.mm; sourceTree = "<group>"; };
|
||||
83C35704180EDD1C007E9DF0 /* MIDIMetadataReader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MIDIMetadataReader.h; sourceTree = "<group>"; };
|
||||
83E83F7A2D9654470054365C /* Accelerate.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Accelerate.framework; path = System/Library/Frameworks/Accelerate.framework; sourceTree = SDKROOT; };
|
||||
83E973451C4378880007F413 /* AUPlayer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = AUPlayer.mm; sourceTree = "<group>"; };
|
||||
83E973461C4378880007F413 /* AUPlayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AUPlayer.h; sourceTree = "<group>"; };
|
||||
83EA54212A6A6CE200CD0580 /* libbass_mpc.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbass_mpc.dylib; path = ../../ThirdParty/BASS/libbass_mpc.dylib; sourceTree = "<group>"; };
|
||||
|
@ -168,6 +170,7 @@
|
|||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
834D190C2D7F954100F13B89 /* CogAudio.framework in Frameworks */,
|
||||
83E83F7B2D9654470054365C /* Accelerate.framework in Frameworks */,
|
||||
8398F2E01C438C7D00EB9639 /* AudioUnit.framework in Frameworks */,
|
||||
83686AB11C5C783000671C7A /* CoreAudioKit.framework in Frameworks */,
|
||||
83B06701180D5747008E3612 /* midi_processing.framework in Frameworks */,
|
||||
|
@ -281,6 +284,7 @@
|
|||
83B06689180D5668008E3612 /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
83E83F7A2D9654470054365C /* Accelerate.framework */,
|
||||
834D190B2D7F954100F13B89 /* CogAudio.framework */,
|
||||
83686AB01C5C783000671C7A /* CoreAudioKit.framework */,
|
||||
83686AAE1C5C780500671C7A /* AudioToolbox.framework */,
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include "AUPlayer.h"
|
||||
#import "AUPlayer.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#import <stdlib.h>
|
||||
|
||||
#import <Accelerate/Accelerate.h>
|
||||
|
||||
#define SF2PACK
|
||||
|
||||
|
@ -82,29 +84,33 @@ void AUPlayer::send_sysex_time(const uint8_t *data, size_t size, size_t port, un
|
|||
}
|
||||
|
||||
void AUPlayer::render(float *out, unsigned long count) {
|
||||
float *ptrL, *ptrR;
|
||||
memset(out, 0, count * sizeof(float) * 2);
|
||||
const float *ptrL, *ptrR;
|
||||
bzero(out, count * sizeof(float) * 2);
|
||||
while(count) {
|
||||
UInt32 numberFrames = count > BLOCK_SIZE ? BLOCK_SIZE : (UInt32)count;
|
||||
|
||||
for(unsigned long i = 0; i < 3; ++i) {
|
||||
AudioUnitRenderActionFlags ioActionFlags = 0;
|
||||
|
||||
bufferList->mNumberBuffers = 2;
|
||||
for(unsigned long j = 0; j < 2; j++) {
|
||||
bufferList->mBuffers[j].mNumberChannels = 1;
|
||||
bufferList->mBuffers[j].mDataByteSize = (UInt32)(numberFrames * sizeof(float));
|
||||
bufferList->mBuffers[j].mData = audioBuffer + j * BLOCK_SIZE;
|
||||
memset(bufferList->mBuffers[j].mData, 0, numberFrames * sizeof(float));
|
||||
bzero(bufferList->mBuffers[j].mData, numberFrames * sizeof(float));
|
||||
}
|
||||
|
||||
AudioUnitRender(samplerUnit[i], &ioActionFlags, &mTimeStamp, 0, numberFrames, bufferList);
|
||||
|
||||
ptrL = (float *)bufferList->mBuffers[0].mData;
|
||||
ptrR = (float *)bufferList->mBuffers[1].mData;
|
||||
for(unsigned long j = 0; j < numberFrames; ++j) {
|
||||
out[j * 2 + 0] += ptrL[j];
|
||||
out[j * 2 + 1] += ptrR[j];
|
||||
}
|
||||
ptrL = (const float *)bufferList->mBuffers[0].mData;
|
||||
ptrR = (const float *)bufferList->mBuffers[1].mData;
|
||||
size_t numBytesL = bufferList->mBuffers[0].mDataByteSize;
|
||||
size_t numBytesR = bufferList->mBuffers[1].mDataByteSize;
|
||||
size_t numBytes = MIN(numBytesL, numBytesR);
|
||||
size_t numFrames = numBytes / sizeof(float);
|
||||
numFrames = MIN(numFrames, numberFrames);
|
||||
vDSP_vadd(ptrL, 1, out, 2, out, 2, numFrames);
|
||||
vDSP_vadd(ptrR, 1, out + 1, 2, out + 1, 2, numFrames);
|
||||
}
|
||||
|
||||
out += numberFrames * 2;
|
||||
|
@ -214,7 +220,7 @@ static OSStatus renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioAct
|
|||
int k = inNumberFrames * sizeof(float);
|
||||
if(k > ioData->mBuffers[i].mDataByteSize)
|
||||
k = ioData->mBuffers[i].mDataByteSize;
|
||||
memset(ioData->mBuffers[i].mData, 0, k);
|
||||
bzero(ioData->mBuffers[i].mData, k);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +228,7 @@ static OSStatus renderCallback(void *inRefCon, AudioUnitRenderActionFlags *ioAct
|
|||
}
|
||||
|
||||
bool AUPlayer::startup() {
|
||||
if(bufferList) return true;
|
||||
if(initialized) return true;
|
||||
|
||||
AudioComponentDescription cd = { 0 };
|
||||
cd.componentType = kAudioUnitType_MusicDevice;
|
||||
|
|
|
@ -148,8 +148,8 @@ unsigned long MIDIPlayer::Play(float *out, unsigned long count) {
|
|||
for(; uStreamPosition < stream_end; uStreamPosition++) {
|
||||
const midi_stream_event &me = mStream.at(uStreamPosition);
|
||||
|
||||
unsigned long samples_todo = me.m_timestamp - uTimeCurrent - into_block;
|
||||
if(samples_todo) {
|
||||
ssize_t samples_todo = me.m_timestamp - uTimeCurrent - into_block;
|
||||
if(samples_todo > 0) {
|
||||
if(samples_todo > count - done) {
|
||||
uSamplesRemaining = samples_todo - (count - done);
|
||||
samples_todo = count - done;
|
||||
|
@ -167,12 +167,14 @@ unsigned long MIDIPlayer::Play(float *out, unsigned long count) {
|
|||
}
|
||||
|
||||
if(needs_block_size) {
|
||||
into_block += samples_todo;
|
||||
while(into_block >= needs_block_size) {
|
||||
render(out + done * 2, needs_block_size);
|
||||
done += needs_block_size;
|
||||
into_block -= needs_block_size;
|
||||
uTimeCurrent += needs_block_size;
|
||||
if(samples_todo > 0) {
|
||||
into_block += samples_todo;
|
||||
while(into_block >= needs_block_size) {
|
||||
render(out + done * 2, needs_block_size);
|
||||
done += needs_block_size;
|
||||
into_block -= needs_block_size;
|
||||
uTimeCurrent += needs_block_size;
|
||||
}
|
||||
}
|
||||
send_event_time_filtered(me.m_event, into_block);
|
||||
} else
|
||||
|
|
Loading…
Reference in a new issue