【问题标题】:record voice in a Queue<byte[]> and send it to the server在 Queue<byte[]> 中录制语音并将其发送到服务器
【发布时间】:2012-11-08 07:42:46
【问题描述】:

我正在开发语音应用程序。

我需要某种缓冲队列,以便我在线程中连续记录,将充满字节的缓冲区放入队列并传输到服务器,然后从队列中取出下一个缓冲区。

这里是录音代码:

     Queue<byte[]> qArray = new LinkedList<byte[]>();
     recordingThread = new Thread(new Runnable() {

        @Override
        public void run() {

            bData = new byte[BufferElements];

            while (isRecording) {
                recorder.read(bData, 0, BufferElements);
                qArray.add(bData);
                if (AudioRecord.ERROR_INVALID_OPERATION != 0) {
                    SendAudio();

                }

            }
        }
    }, "AudioRecorder Thread");
    recordingThread.start();

但在将其发送到服务器时仍然缺少少量 byte[] 数据

这里是发送语音到服务器的代码:

           try {
            HttpClient httpclient = new DefaultHttpClient();


            HttpPost httppost = new HttpPost(ServerUrl.url_audio);

            // Json Format
            JSONObject holder = new JSONObject();
            JSONArray jArray = new JSONArray();
            try {

                byte[] tmparr = qArray.poll();
                for (int i = 0; i < tmparr.length; i++) {
                    jArray.put(i, tmparr[i]);
                }

                holder.put("Voice", jArray);

我不想错过任何正在记录的数据。

任何帮助将不胜感激。谢谢

【问题讨论】:

    标签: java android linked-list bytearray bytebuffer


    【解决方案1】:

    当您将 byte[] 放入队列时,您需要创建一个新缓冲区。否则下一次录制将覆盖相同的缓冲区。只需将bData的初始化移入循环即可:

    Queue<byte[]> qArray = new LinkedList<byte[]>();
    recordingThread = new Thread(new Runnable() {
    
        @Override
        public void run() {
            while (isRecording) {
                bData = new byte[BufferElements];
                recorder.read(bData, 0, BufferElements);
                qArray.add(bData);
                if (AudioRecord.ERROR_INVALID_OPERATION != 0) {
                    SendAudio();
                }
            }
        }
    }, "AudioRecorder Thread");
    recordingThread.start();
    

    您还应该添加逻辑来限制队列的大小。如果队列溢出,你仍然会丢失数据,但至少不会因为内存不足而崩溃。

    编辑 这是一个经过修改的录音循环版本,可以进行正确的错误检查。它使用Queue&lt;ByteBuffer&gt; 而不是Queue&lt;byte[]&gt;

    public void run() {
        bData = ByteBuffer.allocate(BufferElements);
        while (isRecording && !isInterrupted()) {
            int result = recorder.read(bData, 0, BufferElements);
            if (result > 0) {
                qArray.add(bData);
                SendAudio();
                bData = ByteBuffer.allocate(BufferElements);
            } else if (result == AudioRecord.ERROR_INVALID_OPERATION) {
                Log.e("Recording", "Invalid operation error");
                break;
            } else if (result == AudioRecord.ERROR_BAD_VALUE) {
                Log.e("Recording", "Bad value error");
                break;
            } else if (result == AudioRecord.ERROR) {
                Log.e("Recording", "Unknown error");
                break;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                break;
            }
        }
    }
    

    当然,您需要在某个地方致电recorder.startRecording(),否则您将无法获得任何数据。

    【讨论】:

    • 它在发送音频数据时不工作......如果我在 while 循环中移动它,它会将所有空值发送到服务器
    • @GMRamesh - 如果您调试,从队列中检索的数组是否都是空值?
    • @GMRamesh - qArray.poll() 是返回 null 还是返回一个 0 值的数组?如果它返回null,这意味着没有缓冲区被添加到它。如果轮询在与记录不同的线程上运行,您可能需要提供一些同步来查看值。还要确保这两条代码正在访问同一个队列实例。
    • 它只返回一个 0 值的数组......这两段代码只访问同一个队列实例
    • @GMRamesh - 好的,我认为问题出在录制循环中。 recorder.read(...) 根本不需要读取任何数据。您可能应该重写该循环以在对 read 的调用之间暂停一小段时间(例如 50 毫秒)。在缓冲区有数据之前,它也不应该对缓冲区进行排队。此外,由于缓冲区可能未满,您可能需要使用维护字节数计数的数据结构。 ByteBuffer 是一个很好的候选人。您可以在读取循环中将字节填充到其中,当它足够满时,将其排队等待传输并开始另一个。
    猜你喜欢
    • 1970-01-01
    • 2020-04-27
    • 1970-01-01
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    • 2016-12-11
    相关资源
    最近更新 更多