diff -r fac7facfeaa8 Make.osx-x11 --- a/Make.osx-x11 Sat Jan 20 10:42:03 2018 -0500 +++ b/Make.osx-x11 Tue Mar 13 12:07:14 2018 -0700 @@ -9,10 +9,10 @@ O=o OS=posix GUI=x11 -LDADD=-L$(X11)/lib -lX11 -ggdb +LDADD=-L$(X11)/lib -lX11 -ggdb -framework AudioToolbox LDFLAGS=$(PTHREAD) TARG=drawterm -AUDIO=none +AUDIO=core all: default diff -r fac7facfeaa8 kern/devaudio-core.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kern/devaudio-core.c Tue Mar 13 12:07:14 2018 -0700 @@ -0,0 +1,155 @@ +/* + * CoreAudio for 9front drawterm + * kern/devaudio-core.c + * link with -framework AudioToolbox + * Copyright Space Aliens + */ +#include +#undef nil +#include "u.h" +#include "lib.h" +#include "dat.h" +#include "fns.h" +#include "error.h" +#include "devaudio.h" + +enum +{ + Rate = 44100, + Channels = 2, + Bits = 16, + Buffers = 4, + BufferSize = 4096 * 5, + PacketSize = 4, +}; + +static int isopen = 0; +static AudioStreamBasicDescription asbd; +static AudioQueueRef queue; +static AudioQueueBufferRef buffers[Buffers]; +static uchar *rbuf = nil; +static ulong rbuflen = 0; +static int speed = Rate; +static int bufsz = BufferSize; + +static void +audiodevcallback(void *unused, AudioQueueRef queue, AudioQueueBufferRef buffer) +{ + int n = bufsz; + if(n > rbuflen) + n = rbuflen; + memcpy(buffer->mAudioData, rbuf, n); + memset(&buffer->mAudioData[n], 0, bufsz - n); + memmove(rbuf, rbuf + n, rbuflen - n); + rbuflen -= n; + buffer->mAudioDataByteSize = bufsz; + AudioQueueEnqueueBuffer(queue, buffer, 0, nil); +} + +static void +audiodevinit() +{ + int i; + + AudioQueueNewOutput(&asbd, audiodevcallback, nil, nil, nil, 0, &queue); + for(i = 0; i < Buffers; i++){ + AudioQueueAllocateBuffer(queue, bufsz, &buffers[i]); + buffers[i]->mAudioDataByteSize = bufsz; + memset(buffers[i]->mAudioData, 0, bufsz); + AudioQueueEnqueueBuffer(queue, buffers[i], 0, nil); + } + AudioQueueStart(queue, nil); +} + +void +audiodevopen(void) +{ + if(isopen != 0) + oserror(); + isopen = 1; + + asbd.mBitsPerChannel = Bits; + asbd.mBytesPerFrame = Channels * (Bits/8); + asbd.mFramesPerPacket = 1; + asbd.mBytesPerPacket = PacketSize; + asbd.mChannelsPerFrame = Channels; + asbd.mFormatID = kAudioFormatLinearPCM; + asbd.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger; + asbd.mSampleRate = speed; + + audiodevinit(); +} + +void +audiodevclose(void) +{ + while(rbuflen != 0) + usleep(5); + + AudioQueueFlush(queue); + AudioQueueStop(queue, 0); + AudioQueueDispose(queue, 0); + + if(rbuf != nil){ + free(rbuf); + rbuf = nil; + } + rbuflen = 0; + + isopen = 0; +} + +int +audiodevread(void *a, int n) +{ + error("no reading"); + return -1; +} + +int +audiodevwrite(void *a, int n) +{ + double tot; + + rbuf = realloc(rbuf, rbuflen + n); + memcpy(rbuf + rbuflen, a, n); + rbuflen += n; + + if (rbuflen > (bufsz*(Buffers/2))) { + tot = (double)n/(speed*(Bits/8)*Channels); + tot *= 1000; + osmsleep((int)tot); + } + + return n; +} + +void +audiodevsetvol(int what, int left, int right) +{ + int i; + + if(what == Vspeed){ + speed = left; + asbd.mSampleRate = speed; + for(i = 1; ((i+1)*4096)<(speed/2); i++); + bufsz = i * 4096; + if(isopen){ + AudioQueueFlush(queue); + AudioQueueStop(queue, 0); + AudioQueueDispose(queue, 0); + audiodevinit(); + } + } +} + +void +audiodevgetvol(int what, int *left, int *right) +{ + if(what == Vspeed){ + *left = *right = speed; + return; + } + *left = *right = 100; +} +