Одновременное воспроизведение нескольких динамиков - PullRequest
0 голосов
/ 29 октября 2018

Я хочу воспроизводить несколько динамиков одновременно.

В своем заявлении я получаю аудио из сети, декодирую из C #, декодирую по opus, а затем хочу воспроизвести байты. Но теперь я могу играть только на одном динамике.

Мой AudioPLayer.class:

public class Player {
    private static final String TAG = Player.class.getName();
    private AudioTrack audioTrack;
    private boolean isWorking;

    public Player() {
       try  {
           audioTrack = new AudioTrack(
               AudioManager.STREAM_MUSIC,
               AudioConsts.SAMPLERATE,
               AudioConsts.NUM_CHANNELS == 1 ? AudioConsts.CHANNEL_OUT_MONO : AudioConsts.CHANNEL_OUT_STEREO,
               AudioConsts.ENCODING_PCM_16BIT,
               AudioConsts.GetPlayerBufferSize(),
               AudioTrack.MODE_STREAM);
       } catch (Exception e){
           Log.e(TAG, e.toString());
       }
    }

    public void play() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                isWorking = true;

                try {
                    audioTrack.play();
                } catch (Exception e) {
                    Log.d(e.toString(), "AUDIO EXCEPTION");
                    return;
                }

                int bufferSize = AudioConsts.GetPlayerBufferSize();
                while (isWorking){
                    int cursor = audioTrack.getPlaybackHeadPosition();
                    if (cursor > bufferSize){
                        cursor %= bufferSize;

                        audioTrack.flush();
                        audioTrack.setPlaybackHeadPosition(cursor);
                    }
                }
            }
        }).start();
    }

    public void stopReading(){
        if (!isWorking)
            return;

        audioTrack.release();
        isWorking = false;
    }

    public void appendForPlayback(byte[] audioMessage, int size) {
        if (size != 0){
            int writen = audioTrack.write(audioMessage, 0, size);
            if (writen != size) {
                //audioTrack.release();
                Log.d(TAG, "WTF");
            }
        }
    }
}

Также прикрепите инициализацию моего AudioPlayer:

 @Override
public void onCreate() {
    super.onCreate();

    ...

    player = new Player();
    player.play();

    IntentFilter filter = new IntentFilter();
    filter.addAction(ON_UNITY_AUDIO_MESSAGE_RECEIVED);
    filter.addAction(AudioConsts.START_RECORDER);
    filter.addAction(AudioConsts.STOP_RECORDER);

    broadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(ON_UNITY_AUDIO_MESSAGE_RECEIVED)) {
                byte[] decryptedBytes = intent.getByteArrayExtra(UNITY_AUDIO_MESSAGE);

                onUnityAudioReceivedFromNetwork(decryptedBytes);
            } else if (intent.getAction().equals(AudioConsts.START_RECORDER)) {
                incrementSessionCount();
                recorder.startRecording();
            } else if (intent.getAction().equals(AudioConsts.STOP_RECORDER)) {
                recorder.stopRecording();
            }
        }
    };

    registerReceiver(broadcastReceiver, filter);

    decodeMsg = new byte[AudioConsts.FRAME_SIZE * AudioConsts.ENCODING_PCM_16BIT];
    opusDecoder = new OpusDecoder();
    opusDecoder.init(AudioConsts.SAMPLERATE, AudioConsts.NUM_CHANNELS);
}

...

private void onUnityAudioReceivedFromNetwork(byte[] decryptedBytes) {
    UnityAudioMessage audioMessage = UnityAudioMessage.fromBytesSharp(decryptedBytes);
    if (audioMessage != null) {
        try {
            opusDecoder.decode(audioMessage.unityAudioMessage, decodeMsg, AudioConsts.FRAME_SIZE);
        } catch (OpusError e) {
            e.printStackTrace();
            return;
        }

        player.appendForPlayback(decodeMsg, decodeMsg.length);
    }
}

...

Можно ли разрешить одновременное воспроизведение нескольких динамиков?

Также я попытался выпустить его с HaspMap моих игроков. Но это работает только как 1 звуковая дорожка.

1 Ответ

0 голосов
/ 15 ноября 2018

Я много чего перепробовал, но мое решение использует AsyncTask.class

Присоединить Player.class

public class Player {
private static final String TAG = Player.class.getName();
private AudioTrack audioTrack;
private boolean isWorking;

public Player() {
    try {
        audioTrack = new AudioTrack(
                new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_MEDIA)
                        .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH)
                        .setLegacyStreamType(AudioManager.STREAM_MUSIC)
                        .build(),

                new AudioFormat.Builder()
                        .setChannelMask(AudioFormat.CHANNEL_OUT_MONO)
                        .setEncoding(AudioFormat.ENCODING_PCM_16BIT)
                        .setSampleRate(AudioConsts.SAMPLERATE)
                        .build(),

                AudioConsts.GetPlayerBufferSize(),
                AudioTrack.MODE_STREAM,
                AudioManager.AUDIO_SESSION_ID_GENERATE);

    } catch (Exception e) {
        Log.e(TAG, e.toString());
    }
}

public void play() {
    audioTrack.play();
}

public void stopReading() {
    if (!isWorking)
        return;

    audioTrack.release();
    isWorking = false;
}

public void appendForPlayback(byte[] audioMessage, int size) {
    new Executor().doInBackground(audioMessage);
}

private class Executor extends AsyncTask<byte[], Void, Void> {
    @Override
    protected Void doInBackground(byte[]... bytes) {
        for (byte[] audioMessage : bytes) {
            if (audioMessage.length != 0) {
                int writen = audioTrack.write(audioMessage, 0, audioMessage.length);
                if (writen != audioMessage.length) {
                    Log.d(TAG, "WTF");
                }
            }

        }

        return null;
    }
}}
...