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 16:19:28 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 16:19:28 2018 -0700 @@ -0,0 +1,169 @@ +/* + * 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[0x200000]; +#define rbuflen 0x200000 +static ulong rrbuf = 0; +static ulong wrbuf = 0; +static int speed = Rate; +static int bufsz = BufferSize; + +static void +audiodevcallback(void *unused, AudioQueueRef queue, AudioQueueBufferRef buffer) +{ + int ridx; + int n; + int len = wrbuf - rrbuf; + if (len > bufsz) + len = bufsz; + ridx = rrbuf & (rbuflen-1); + n = rbuflen - ridx; + if (n >= len) { + memcpy(buffer->mAudioData, &rbuf[ridx], len); + } else { + memcpy(buffer->mAudioData, &rbuf[ridx], n); + memcpy(&buffer->mAudioData[n], rbuf, len - n); + } + memset(&buffer->mAudioData[n], 0, bufsz - len); + rrbuf += len; + 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((wrbuf - rrbuf) > 0) + usleep(5); + + AudioQueueFlush(queue); + AudioQueueStop(queue, 0); + AudioQueueDispose(queue, 0); + + rrbuf = wrbuf = 0; + + isopen = 0; +} + +int +audiodevread(void *a, int n) +{ + error("no reading"); + return -1; +} + +int +audiodevwrite(void *a, int n) +{ + double tot; + ulong len; + int idx; + + idx = wrbuf & (rbuflen-1); + len = rbuflen - idx; + if (len >= n) + memcpy(&rbuf[idx], a, n); + else { + memcpy(&rbuf[idx], a, len); + memcpy(rbuf, a + len, n - len); + } + wrbuf += n; + + if ((wrbuf - rrbuf) > (BufferSize * 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; +} +