使用音频队列录制演示的 RoboVM 实现会导致"No @Marshaler found"错误



我正在尝试使用Apple的AudioQueue指南和他们的示例SpeakHere项目使用RoboVM实现iOS音频录制并遇到此错误:

No @Marshaler found for parameter 1 of @Callback method <AQRecorder: void HandleInputBuffer(AQRecorder,org.robovm.apple.audiotoolbox.AudioQueue,org.robovm.apple.audiotoolbox.AudioQueueBuffer,org.robovm.apple.coreaudio.AudioTimeStamp,int,org.robovm.apple.coreaudio.AudioStreamPacketDescription)>

有什么想法吗?这是我使用的代码:

主.java:

import org.robovm.apple.coregraphics.CGRect;
import org.robovm.apple.foundation.NSAutoreleasePool;
import org.robovm.apple.uikit.UIApplication;
import org.robovm.apple.uikit.UIApplicationDelegateAdapter;
import org.robovm.apple.uikit.UIApplicationLaunchOptions;
import org.robovm.apple.uikit.UIButton;
import org.robovm.apple.uikit.UIButtonType;
import org.robovm.apple.uikit.UIColor;
import org.robovm.apple.uikit.UIControl;
import org.robovm.apple.uikit.UIControlState;
import org.robovm.apple.uikit.UIEvent;
import org.robovm.apple.uikit.UIScreen;
import org.robovm.apple.uikit.UIWindow;
public class IOSDemo extends UIApplicationDelegateAdapter {
    private UIWindow window = null;
    @Override
    public boolean didFinishLaunching(UIApplication application, 
            UIApplicationLaunchOptions launchOptions) {
        final AQRecorder aqRecorder = new AQRecorder();
        final UIButton button = UIButton.create(UIButtonType.RoundedRect);
        button.setFrame(new CGRect(115.0f, 121.0f, 91.0f, 37.0f));
        button.setTitle("Start", UIControlState.Normal);
        button.addOnTouchUpInsideListener(new UIControl.OnTouchUpInsideListener() {
            @Override
            public void onTouchUpInside(UIControl control, UIEvent event) {
                if(button.getTitle(UIControlState.Normal) == "Stop"){
                    aqRecorder.stopRecord();
                    button.setTitle("Start", UIControlState.Normal);
                }
                else{
                    aqRecorder.startRecord();
                    button.setTitle("Stop", UIControlState.Normal);
                }
            }
        });
        window = new UIWindow(UIScreen.getMainScreen().getBounds());
        window.setBackgroundColor(UIColor.lightGray());
        window.addSubview(button);
        window.makeKeyAndVisible();
        try {
            aqRecorder.setUpAudioFormat();
        } catch (NoSuchMethodException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return true;
    }
    public static void main(String[] args) {
        try (NSAutoreleasePool pool = new NSAutoreleasePool()) {
            UIApplication.main(args, null, IOSDemo.class);
        }
    }
}

AQRecorder.java:

 import org.robovm.apple.audiotoolbox.AudioFile;
import org.robovm.apple.audiotoolbox.AudioQueue;
import org.robovm.apple.audiotoolbox.AudioQueueBuffer;
import org.robovm.apple.audiotoolbox.AudioQueue.AudioQueuePtr;
import org.robovm.apple.coreaudio.AudioFormat;
import org.robovm.apple.coreaudio.AudioStreamBasicDescription;
import org.robovm.apple.coreaudio.AudioStreamPacketDescription;
import org.robovm.apple.coreaudio.AudioTimeStamp;
import org.robovm.rt.bro.annotation.Callback;
import org.robovm.rt.bro.ptr.FunctionPtr;
import org.robovm.rt.bro.ptr.VoidPtr;
public class AQRecorder {
        AudioStreamBasicDescription  mDataFormat;                   // 2
        AudioQueue                mQueue;                        // 3
        //AudioQueueBufferRef          mBuffers[kNumberBuffers];      // 4
        AudioFile                  mAudioFile;                    // 5
        int                      bufferByteSize;                // 6
        int                       mCurrentPacket;                // 7
        boolean                         mIsRunning;                    // 8
        public void startRecord(){
            mQueue.start(null);
        }
        public void stopRecord(){
            mQueue.stop(true);
        }
        @Callback
        static void HandleInputBuffer(
                AQRecorder                           aqData,
                AudioQueue                        inAQ,
                AudioQueueBuffer                  inBuffer,
                AudioTimeStamp                 inStartTime,
                int                               inNumPackets,
                AudioStreamPacketDescription   inPacketDesc
            ) {
                AQRecorder pAqData = aqData;               // 1
                if (inNumPackets == 0 && pAqData.mDataFormat.mBytesPerPacket() != 0)
                   inNumPackets = inBuffer.mAudioDataByteSize() / pAqData.mDataFormat.mBytesPerPacket();
               if (!aqData.mIsRunning)                                         // 5
                  return;
               System.out.println(inBuffer.mAudioData());
            }
        void setUpAudioFormat() throws NoSuchMethodException{
            mDataFormat = new AudioStreamBasicDescription(
                        16000, // mSampleRate
                        AudioFormat.LinearPCM, // mFormatID
                        (1 << 2), // mFormatFlags
                        512, // mBytesPerPacket
                        1, // mFramesPerPacket
                        512, // mBytesPerFrame
                        1, // mChanneslPerFrame
                        16, // mBitsPerChannel
                        0 // mReserved
                    );
            AudioQueuePtr mQueuePtr = new AudioQueuePtr();
            mQueuePtr.set(mQueue);
            VoidPtr self = new VoidPtr();
            @SuppressWarnings("rawtypes")
            Class[] cArg = new Class[6];
            cArg[0] = AQRecorder.class;
            cArg[1] = AudioQueue.class;
            cArg[2] = AudioQueueBuffer.class;
            cArg[3] = AudioTimeStamp.class;
            cArg[4] = int.class;
            cArg[5] = AudioStreamPacketDescription.class;
            FunctionPtr handleInputBuffer = new FunctionPtr((AQRecorder.class).getDeclaredMethod("HandleInputBuffer", cArg));
            AudioQueue.newInput(mDataFormat, handleInputBuffer, self, null, "", 0, mQueuePtr);
        }
    };
 

使用 RoboVM 1.0.0-beta-3,我终于能够让音频录制和播放正常工作。不知道为什么录制音频队列最多需要 20 秒才能停止,但这里有一些适用于模拟器和我的 iPhone 4 的示例代码:

主类:

import java.util.Vector;
import org.robovm.apple.coregraphics.*;
import org.robovm.apple.foundation.*;
import org.robovm.apple.uikit.*;
public class TestAudioQueueCrash extends UIApplicationDelegateAdapter
{
       private UIWindow window = null;
        private int clickCount = 0;
        @Override
        public boolean didFinishLaunching(UIApplication application, UIApplicationLaunchOptions launchOptions) 
        {
            final UIButton button = UIButton.create(UIButtonType.RoundedRect);
            button.setFrame(new CGRect(15.0f, 121.0f, 291.0f, 37.0f));
            button.setTitle("Click me!", UIControlState.Normal);
            button.addOnTouchUpInsideListener(new UIControl.OnTouchUpInsideListener() 
            {
                @Override
                public void onTouchUpInside(UIControl control, UIEvent event) 
                {
                    if (clickCount == 0)
                    {
                        button.setTitle("Recording for 5 seconds... (SPEAK!)", UIControlState.Normal);
                        Runnable r = new Runnable() 
                        {
                            public void run() 
                            {
                                try
                                {
                                    clickCount = 1;
                                    AudioRecord record = new AudioRecord();
                                    record.startRecording();
                                    long when = System.currentTimeMillis() + 5000;
                                    final Vector<byte[]> v = new Vector();
                                    byte[] ba = new byte[3072];
                                    while (System.currentTimeMillis() < when)
                                    {
                                        int n = 0;
                                        while (n<3072)
                                        {
                                            int i = record.read(ba, n, 3072-n);
                                            if (i==-1 || i == 0) break;
                                            n += i;
                                        }
                                        if (n>0)
                                        {
                                            byte[] ba2 = new byte[n];
                                            System.arraycopy(ba, 0, ba2, 0, n);
                                            v.addElement(ba2);
                                        }
                                    }
                                    System.out.println("DONE RECORDING");
                                    record.release();
                                    System.out.println("RECORDER STOPPED");
                                    System.out.println("Playing back recorded audio...");
                                    button.setTitle("Playing back recorded audio...", UIControlState.Normal);
                                    AudioTrack at = new AudioTrack();
                                    at.play();
                                    while (v.size() > 0) 
                                    {
                                        ba = v.remove(0);
                                        at.write(ba, 0, ba.length);
                                        Thread.yield();
                                    }
                                    at.stop();
                                    button.setTitle("DONE", UIControlState.Normal);
                                    System.out.println("FINISHED PIPING AUDIO");
                                }
                                catch (Exception x)
                                {
                                    x.printStackTrace();
                                    button.setTitle("ERROR: " + x.getMessage(), UIControlState.Normal);
                                }
                                clickCount = 0;
                            }
                        };
                        new Thread(r).start();
                    }
                }
            });
            window = new UIWindow(UIScreen.getMainScreen().getBounds());
            window.setBackgroundColor(UIColor.lightGray());
            window.addSubview(button);
            window.makeKeyAndVisible();
            return true;
        }
        public static void main(String[] args) 
        {
            try (NSAutoreleasePool pool = new NSAutoreleasePool()) 
            {
                UIApplication.main(args, null, TestAudioQueueCrash.class);
            }
        }
}

AQRecorderState:

/*<imports>*/
import java.util.Hashtable;
import org.robovm.rt.bro.*;
import org.robovm.rt.bro.annotation.*;
import org.robovm.rt.bro.ptr.*;
/*</imports>*/
/*<javadoc>*/
/*</javadoc>*/
/*<annotations>*//*</annotations>*/
/*<visibility>*/public/*</visibility>*/ class /*<name>*/AQRecorderState/*</name>*/ 
    extends /*<extends>*/Struct<AQRecorderState>/*</extends>*/ 
    /*<implements>*//*</implements>*/ {
    protected static Hashtable<Integer, AudioRecord> mAudioRecords = new Hashtable<>();
    protected static int mLastID = 0;
    /*<ptr>*/public static class AQRecorderStatePtr extends Ptr<AQRecorderState, AQRecorderStatePtr> {}/*</ptr>*/
    /*<bind>*/
    /*</bind>*/
    /*<constants>*//*</constants>*/
    /*<constructors>*/
    public AQRecorderState() {}
    public AQRecorderState(AudioRecord ar) 
    {
        this.mID(++mLastID);
        mAudioRecords.put(mID(), ar);
    }
    /*</constructors>*/
    /*<properties>*//*</properties>*/
    /*<members>*/
    @StructMember(0) public native int mID();
    @StructMember(0) public native AQRecorderState mID(int mID);
    /*</members>*/
    /*<methods>*//*</methods>*/
    public AudioRecord getRecord()
    {
        return mAudioRecords.get(mID());
    }
    public static void drop(int mStateID) 
    {
        mAudioRecords.remove(mStateID);
    }
}

录音:

import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.lang.reflect.Method;
import org.robovm.apple.audiotoolbox.AudioQueue;
import org.robovm.apple.audiotoolbox.AudioQueue.AudioQueuePtr;
import org.robovm.apple.audiotoolbox.AudioQueueBuffer;
import org.robovm.apple.audiotoolbox.AudioQueueBuffer.AudioQueueBufferPtr;
import org.robovm.apple.audiotoolbox.AudioQueueError;
import org.robovm.apple.coreaudio.AudioFormat;
import org.robovm.apple.coreaudio.AudioStreamBasicDescription;
import org.robovm.apple.coreaudio.AudioStreamPacketDescription.AudioStreamPacketDescriptionPtr;
import org.robovm.apple.coreaudio.AudioTimeStamp.AudioTimeStampPtr;
import org.robovm.apple.coreaudio.CoreAudio;
import org.robovm.apple.corefoundation.CFRunLoopMode;
import org.robovm.rt.VM;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Callback;
import org.robovm.rt.bro.annotation.Library;
import org.robovm.rt.bro.annotation.Pointer;
import org.robovm.rt.bro.ptr.FunctionPtr;
import org.robovm.rt.bro.ptr.VoidPtr;
/*<annotations>*/@Library("AudioToolbox")/*</annotations>*/
public class AudioRecord
{
    protected double mSampleRate;
    protected AudioFormat mFormatID;
    protected int mFormatFlags;
    protected int mBytesPerPacket;
    protected int mFramesPerPacket;
    protected int mBytesPerFrame;
    protected int mChannelsPerFrame;
    protected int mBitsPerChannel;  
    protected AudioQueue mQueue = null;
    private int kNumberBuffers = 3;
    private PipedInputStream mPIS;
    private PipedOutputStream mPOS;
    private int mStateID = -1;
    private boolean mRunning = false;
    public AudioRecord() throws IOException 
    {
        mSampleRate = 44100;
        mFormatID = AudioFormat.LinearPCM;
        mFormatFlags = CoreAudio.AudioFormatFlagIsPacked | CoreAudio.AudioFormatFlagIsSignedInteger;
        mBytesPerPacket = 2;
        mFramesPerPacket = 1;
        mBytesPerFrame = 2;
        mChannelsPerFrame = 1;
        mBitsPerChannel = 16;    
        mPOS = new PipedOutputStream();
        mPIS = new PipedInputStream(mPOS);
    }
    public static int getMinBufferSize(int sampleRate, int channelConfig, int audioFormat) 
    {
        // TODO Auto-generated method stub
        return 0;
    }
    public int deriveBufferSize(AudioQueue audioQueue, AudioStreamBasicDescription ASBDescription, double seconds)
    {
        int maxBufferSize = 0x50000;
        int maxPacketSize = ASBDescription.getMBytesPerPacket();
        System.out.println(3);
        double numBytesForTime = ASBDescription.getMSampleRate() * maxPacketSize * seconds;
        return (int)(numBytesForTime < maxBufferSize ? numBytesForTime : maxBufferSize);
    }
    public void release() 
    {
        System.out.println("RECORD QUEUE STOPPING...");
        mRunning = false;
        mQueue.stop(true);
//      mQueue.dispose(true);
        System.out.println("RECORD QUEUE STOPPED");
        try
        {
            mPOS.close();
            mPIS.close();
            AQRecorderState.drop(mStateID);
        }
        catch (Exception x) { x.printStackTrace(); }
    }
    public int read(byte[] abData, int i, int length) throws IOException 
    {
        return mPIS.read(abData, i, length);
    }
    /*<bind>*/static { Bro.bind(AudioRecord.class); }/*</bind>*/
    /*<constants>*//*</constants>*/
    /*<constructors>*//*</constructors>*/
    /*<properties>*//*</properties>*/
    /*<members>*//*</members>*/
    @Callback
    public static void callbackMethod(
            @Pointer long                     refcon,
            AudioQueue                        inAQ,
            AudioQueueBuffer                  inBuffer,
            AudioTimeStampPtr                 inStartTime,
            int                               inNumPackets,
            AudioStreamPacketDescriptionPtr   inPacketDesc
        )
    {
        try
        {
            System.out.println("a");
            AQRecorderState.AQRecorderStatePtr ptr = new AQRecorderState.AQRecorderStatePtr();
            ptr.set(refcon);
            System.out.println("b");
            AQRecorderState aqrs = ptr.get();
            System.out.println("c");
            byte[] ba = VM.newByteArray(inBuffer.getMAudioData().getHandle(), inBuffer.getMAudioDataByteSize());
            System.out.println("d");
            aqrs.getRecord().receive(ba);
            System.out.println("e");
        }
        catch (Exception x) { x.printStackTrace(); }
        inAQ.enqueueBuffer(inBuffer, 0, null);
        System.out.println("f");
    }
    private void receive(byte[] ba) 
    {
        if (mRunning) try { mPOS.write(ba); } catch (Exception x) { x.printStackTrace(); }
    }
    public void startRecording() throws Exception
    {
        AudioStreamBasicDescription asbd = new AudioStreamBasicDescription(mSampleRate, mFormatID, mFormatFlags, mBytesPerPacket, mFramesPerPacket, mBytesPerFrame, mChannelsPerFrame, mBitsPerChannel, 0);
        AudioQueuePtr mQueuePtr = new AudioQueuePtr();
        AudioQueueBufferPtr mBuffers = Struct.allocate(AudioQueueBufferPtr.class, kNumberBuffers);
        System.out.println(11);
        AQRecorderState aqData = new AQRecorderState(this);
        mStateID = aqData.mID();
        System.out.println(12);
        Method callbackMethod = null;
        Method[] methods = this.getClass().getMethods();
        int i = methods.length;
        while (i-->0) if (methods[i].getName().equals("callbackMethod")) 
        {
            callbackMethod = methods[i];
            break;
        }
        FunctionPtr fp = new FunctionPtr(callbackMethod );
        System.out.println(13);
        VoidPtr vp = aqData.as(VoidPtr.class);
        System.out.println(14);
        AudioQueueError aqe = AudioQueue.newInput(asbd, fp, vp, null, null, 0, mQueuePtr);
        System.out.println(CFRunLoopMode.Common.value());
        System.out.println(aqe.name());
        mQueue = mQueuePtr.get();
        System.out.println(2);
        int bufferByteSize = deriveBufferSize(mQueue, asbd, 0.5);
        System.out.println("BUFFER SIZE: "+bufferByteSize);
        AudioQueueBufferPtr[] buffers = mBuffers.toArray(kNumberBuffers);
        for (i = 0; i < kNumberBuffers; ++i) 
        {
            mQueue.allocateBuffer(bufferByteSize, buffers[i]);
            mQueue.enqueueBuffer(buffers[i].get(), 0, null);
        }
        mRunning = true;
        mQueue.start(null);
    }
}

AQPlayerState:

/*<imports>*/
import java.util.Hashtable;
import org.robovm.rt.bro.*;
import org.robovm.rt.bro.annotation.*;
import org.robovm.rt.bro.ptr.*;
/*</imports>*/
/*<javadoc>*/
/*</javadoc>*/
/*<annotations>*//*</annotations>*/
/*<visibility>*/public/*</visibility>*/ class /*<name>*/AQPlayerState/*</name>*/ 
    extends /*<extends>*/Struct<AQPlayerState>/*</extends>*/ 
    /*<implements>*//*</implements>*/ {
    protected static Hashtable<Integer, AudioTrack> mAudioTracks = new Hashtable<>();
    protected static int mLastID = 0;
    /*<ptr>*/public static class AQPlayerStatePtr extends Ptr<AQPlayerState, AQPlayerStatePtr> {}/*</ptr>*/
    /*<bind>*/
    /*</bind>*/
    /*<constants>*//*</constants>*/
    /*<constructors>*/
    public AQPlayerState() {}
    public AQPlayerState(AudioTrack ar) 
    {
        this.mID(++mLastID);
        this.mID2(mLastID);
        mAudioTracks.put(mID(), ar);
    }
    /*</constructors>*/
    /*<properties>*//*</properties>*/
    /*<members>*/
    @StructMember(0) public native int mID();
    @StructMember(0) public native AQPlayerState mID(int mID);
    @StructMember(1) public native int mID2();
    @StructMember(1) public native AQPlayerState mID2(int mID2);
    /*</members>*/
    /*<methods>*//*</methods>*/
    public AudioTrack getTrack()
    {
        return mAudioTracks.get(mID());
    }
    public static void drop(int mStateID) 
    {
        mAudioTracks.remove(mStateID);
    }
}

音轨:

import java.lang.reflect.Method;
import java.util.Vector;
import org.robovm.apple.audiotoolbox.AudioQueue;
import org.robovm.apple.audiotoolbox.AudioQueueBuffer;
import org.robovm.apple.audiotoolbox.AudioQueue.AudioQueuePtr;
import org.robovm.apple.audiotoolbox.AudioQueueBuffer.AudioQueueBufferPtr;
import org.robovm.apple.audiotoolbox.AudioQueueError;
import org.robovm.apple.audiotoolbox.AudioQueueParam;
import org.robovm.apple.coreaudio.AudioFormat;
import org.robovm.apple.coreaudio.AudioStreamBasicDescription;
import org.robovm.apple.coreaudio.CoreAudio;
import org.robovm.rt.bro.Bro;
import org.robovm.rt.bro.Struct;
import org.robovm.rt.bro.annotation.Callback;
import org.robovm.rt.bro.annotation.Pointer;
import org.robovm.rt.bro.ptr.BytePtr;
import org.robovm.rt.bro.ptr.FunctionPtr;
import org.robovm.rt.bro.ptr.VoidPtr;

public class AudioTrack {
    public static final int MODE_STREAM = -1;
    private int kNumberBuffers = 3;
    private Vector<byte[]> mData = new Vector<>();
    private int mStateID = -1;
    private boolean mRunning = false;
    protected double mSampleRate;
    protected AudioFormat mFormatID;
    protected int mFormatFlags;
    protected int mBytesPerPacket;
    protected int mFramesPerPacket;
    protected int mBytesPerFrame;
    protected int mChannelsPerFrame;
    protected int mBitsPerChannel;  
    protected AudioQueue mQueue = null;
    public AudioTrack() 
    {
        mSampleRate = 44100;
        mFormatID = AudioFormat.LinearPCM;
        mFormatFlags = CoreAudio.AudioFormatFlagIsPacked | CoreAudio.AudioFormatFlagIsSignedInteger;
        mBytesPerPacket = 2;
        mFramesPerPacket = 1;
        mBytesPerFrame = 2;
        mChannelsPerFrame = 1;
        mBitsPerChannel = 16;    
    }
    public static int getMinBufferSize(int sampleRate, int channelConfigurationMono, int encodingPcm16bit) 
    {
        // TODO Auto-generated method stub
        return 0;
    }
    public int deriveBufferSize(AudioStreamBasicDescription ASBDescription, int maxPacketSize, double seconds)
    {
        int maxBufferSize = 0x50000;
        int minBufferSize = 0x4000;
        double numPacketsForTime = ASBDescription.getMSampleRate() / ASBDescription.getMFramesPerPacket() * seconds;
        int outBufferSize = (int)(numPacketsForTime * maxPacketSize);
        if (outBufferSize > maxBufferSize) return maxBufferSize;
        if (outBufferSize < minBufferSize) return minBufferSize;
        return outBufferSize;
    }
    /*<bind>*/static { Bro.bind(AudioTrack.class); }/*</bind>*/
    /*<constants>*//*</constants>*/
    /*<constructors>*//*</constructors>*/
    /*<properties>*//*</properties>*/
    /*<members>*//*</members>*/
    @Callback
    public static void callbackMethod(
            @Pointer long                     refcon,
            AudioQueue                        inAQ,
            AudioQueueBuffer                  inBuffer
        )
    {
        System.out.println("In Callback");
        AQPlayerState.AQPlayerStatePtr ptr = new AQPlayerState.AQPlayerStatePtr();
        ptr.set(refcon);
        AQPlayerState aqps = ptr.get();
        AudioTrack me = aqps.getTrack();
        me.nextChunk(inAQ, inBuffer);
    }
    private void nextChunk(AudioQueue inAQ, AudioQueueBuffer inBuffer) 
    {
        byte[] ba = null;
        long when = System.currentTimeMillis() + 30000;
        while (mRunning && System.currentTimeMillis() < when)
        {
            if (mData.size() > 0)
            {
                ba = mData.remove(0);
                break;
            }
            try { Thread.yield(); } catch (Exception x) { x.printStackTrace(); }
        }
        if (ba == null) ba = new byte[0];
        System.out.println("PLAYING BYTES: "+ba.length);
        if (ba.length>0)
        {
            VoidPtr vp = inBuffer.getMAudioData();
            BytePtr bp = vp.as(BytePtr.class); //Struct.allocate(BytePtr.class, ba.length);
            bp.set(ba);
//          inBuffer.setMAudioData(vp);
            inBuffer.setMAudioDataByteSize(ba.length);
        }
        mQueue.enqueueBuffer(inBuffer, 0, null);
    }
    public void play() 
    {
        final AudioTrack me = this;
        Runnable r = new Runnable() 
        {
            public void run() 
            {
                AudioStreamBasicDescription asbd = new AudioStreamBasicDescription(mSampleRate, mFormatID, mFormatFlags, mBytesPerPacket, mFramesPerPacket, mBytesPerFrame, mChannelsPerFrame, mBitsPerChannel, 0);
                AudioQueuePtr mQueuePtr = new AudioQueuePtr();
                Method callbackMethod = null;
                Method[] methods = me.getClass().getMethods();
                int i = methods.length;
                while (i-->0) if (methods[i].getName().equals("callbackMethod")) 
                {
                    callbackMethod = methods[i];
                    break;
                }
                FunctionPtr fp = new FunctionPtr(callbackMethod );
                AQPlayerState aqData = new AQPlayerState(me);
                mStateID = aqData.mID();
                VoidPtr vp = aqData.as(VoidPtr.class);
//              AudioQueueError aqe = AudioQueue.newOutput(asbd, fp, vp, CFRunLoop.getCurrent(), new CFString(CFRunLoopMode.Common.value()), 0, mQueuePtr);
                AudioQueueError aqe = AudioQueue.newOutput(asbd, fp, vp, null, null, 0, mQueuePtr);
                System.out.println(aqe.name());
                mQueue = mQueuePtr.get();
                int bufferByteSize = deriveBufferSize(asbd, 2, 0.5);
                System.out.println("BUFFER SIZE: "+bufferByteSize);
                System.out.println("Volume PARAM:"+(int)AudioQueueParam.Volume.value());
                mQueue.setParameter((int)AudioQueueParam.Volume.value(), 1.0f);
                mRunning = true;
                AudioQueueBufferPtr mBuffers = Struct.allocate(AudioQueueBufferPtr.class, kNumberBuffers);
                AudioQueueBufferPtr[] buffers = mBuffers.toArray(kNumberBuffers);
                for (i = 0; i < kNumberBuffers; ++i) 
                {
                    mQueue.allocateBuffer(bufferByteSize, buffers[i]);
                    nextChunk(mQueue, buffers[i].get());
                }
                System.out.println("STARTING QUEUE");
                mQueue.start(null);
                System.out.println("QUEUE STARTED");
/*              
                System.out.println("RUNNING LOOP");
                do
                {
                    System.out.print(".");
                    CFRunLoop.runInMode(CFRunLoopMode.Default, 0.25, false);
                    System.out.print("#");
                }
                while (mRunning);
                System.out.println("!!!");
                CFRunLoop.runInMode(CFRunLoopMode.Default, 1, false);
                System.out.println("DONE RUNNING LOOP");
                mQueue.stop(true);
                AQPlayerState.drop(mStateID);
                System.out.println("QUEUE STOPPED");
*/
            }
        };
        new Thread(r).start();
    }
    public void write(byte[] ba, int i, int length) 
    {
        while (mData.size() > 10) Thread.yield();
        System.out.println("SOUND IN: "+length+" bytes");
        mData.addElement(ba);
    }
    public void stop() 
    {
        System.out.println("STOPPING AUDIO PLAYER");
        mRunning = false;
        mQueue.stop(true);
        AQPlayerState.drop(mStateID);
    }
    public void release() 
    {
        // TODO Auto-generated method stub
    }
}

相关内容

  • 没有找到相关文章

最新更新