简体   繁体   English

绘图和音频在 Java Android 应用程序中无法协同工作

[英]Drawing and audio not working together in Java Android App

I am currenty doing a small game.我目前正在做一个小游戏。 But my application does not work properly.但是我的应用程序无法正常工作。 Program does not stop with error, but firstly it playes part of track, and after that (around 5-10 seconds) it stops and drawing begins.程序不会因错误而停止,但首先它会播放曲目的一部分,然后(大约 5-10 秒)它会停止并开始绘制。

Without audio added, code works absolutely fine.没有添加音频,代码工作得很好。

I also tested app on several different devices and emulators, but issue keeps occuring.我还在几种不同的设备和模拟器上测试了应用程序,但问题不断发生。

Here are some methods from class "Game.java", where I am trying to implement audio.以下是“Game.java”类中的一些方法,我试图在其中实现音频。

public class Game {
    Plane background;
    Plane playfield;
    Context context;
    List<SingleNote> notes = new ArrayList<SingleNote>();
    List<SingleNote> notes_to_compute = new ArrayList<SingleNote>();
    Date date = new Date();
    long time_initial;
    float[] touch_coord = new float[2];
    private int mStreamId;

    public Game(Context context){
        this.context = context;
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    public void load(){
        background = new Plane(context, R.raw.vertex_shader, R.raw.fragment_shader, R.drawable._map1);
        playfield = new Plane(context, R.raw.vertex_shader, R.raw.fragment_shader, R.drawable.s_playfield);
        InitNotes(R.raw._map1);
        time_initial = date.getTime();
        MyThread m = new MyThread();
        m.context = context;
        m.start();
    }

    @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR1)
    public void draw(){
        background.draw();
        playfield.draw();
        update();
    }
}


class MyThread extends Thread {
    Context context;
    public void run(){
        SoundManagement.playSoundPool(context, R.raw._map1_a);
    }
}

And static PlaySondPool method in class和类中的静态 PlaySondPool 方法

    public static void playSoundPool(Context context, int soundID) {
        int MAX_STREAMS = 20;
        int REPEAT = 0;
        SoundPool soundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, REPEAT);
        soundPool.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
            @Override
            public void onLoadComplete(SoundPool soundPool, int soundId, int status) {
                int priority = 0;
                int repeat = 0;
                float rate = 1.f; // Frequency Rate can be from .5 to 2.0
                // Set volume
                AudioManager mgr = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
                float streamVolumeCurrent =
                        mgr.getStreamVolume(AudioManager.STREAM_MUSIC);
                float streamVolumeMax =
                        mgr.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
                float volume = streamVolumeCurrent / streamVolumeMax;
                // Play it
                soundPool.play(soundId, volume, volume, priority, repeat, rate);
            }
        });
        soundPool.load(context, soundID, 1);
    }

I thought using separate thread would help, but same issue occurs.我认为使用单独的线程会有所帮助,但发生了同样的问题。 What should I do in order to avoid this error?我应该怎么做才能避免这个错误? Maybe use another library, or play sound from other class?也许使用另一个库,或播放其他类的声音?

Whole code here: https://github.com/arthur100500/AndroidProject整个代码在这里: https : //github.com/arthur100500/AndroidProject

Additional debug ingormation from android studio来自 android studio 的额外调试信息

Logcat: https://pastebin.com/MQSaWw8R Logcat: https ://pastebin.com/MQSaWw8R

Run: https://pastebin.com/5D4AGuHZ运行: https : //pastebin.com/5D4AGuHZ

How it looks: https://youtu.be/X7IBquHs1jA外观: https : //youtu.be/X7IBquHs1jA

I think there is every likelihood that the choice of SoundPool for playback is the source of the problem you are experiencing.我认为选择SoundPool进行播放很可能是您遇到问题的根源。 SoundPool is designed for the handling of audio files that are short (a couple seconds) and can be held in memory. SoundPool设计用于处理短(几秒钟)并且可以保存在内存中的音频文件。 You've indicated that you are trying to use it to play a 5-minute long file.您已表示您正尝试使用它来播放 5 分钟长的文件。 According to the documentation in the API , only the first MB of the 5-minute file is being handled.根据API 中的文档,仅处理 5 分钟文件的前 MB。

Soundpool sounds are expected to be short as they are predecoded into memory. Soundpool 声音预计会很短,因为它们被预解码到内存中。 Each decoded sound is internally limited to one megabyte storage, which represents approximately 5.6 seconds at 44.1kHz stereo (the duration is proportionally longer at lower sample rates or a channel mask of mono).每个解码的声音在内部被限制为 1 兆字节的存储空间,在 44.1kHz 立体声下大约为 5.6 秒(持续时间在较低的采样率或单声道的通道掩码下成比例地更长)。 A decoded audio sound will be truncated if it would exceed the per-sound one megabyte storage space.如果解码后的音频超过每个声音 1 兆字节的存储空间,它将被截断。

Streaming via an AudioTrack should be a more fitting alternative for this sound file.通过AudioTrack进行流式传输应该是更适合此声音文件的替代方案。

An AudioTrack instance can operate under two modes: static or streaming. AudioTrack 实例可以在两种模式下运行:静态或流媒体。 In Streaming mode, the application writes a continuous stream of data to the AudioTrack, using one of the write() methods.在流模式下,应用程序使用 write() 方法之一将连续的数据流写入 AudioTrack。 These are blocking and return when the data has been transferred from the Java layer to the native layer and queued for playback.当数据已从 Java 层传输到本机层并排队等待播放时,这些将阻塞并返回。 The streaming mode is most useful when playing blocks of audio data that for instance are:流式传输模式在播放音频数据块时最有用,例如:

  • too big to fit in memory because of the duration of the sound to play,由于播放声音的持续时间太大而无法放入内存中,
  • too big to fit in memory because of the characteristics of the audio data (high sampling rate, bits per sample ...)由于音频数据的特性(高采样率,每个样本的位数......),太大而无法放入内存
  • received or generated while previously queued audio is playing.在播放先前排队的音频时接收或生成。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM