본문 바로가기
Game Programming

Android AudioTrack

by 게임혼 2010. 7. 9.

일단 원인 불명의 이유로
SoundPool Load에서 에러가 발생한다. 의심은 가는데 귀찮아서 손은 못대고
전부터 할까말까 고민하던 AudioTrack을 건들기로 했다.

WavData 클래스가 없는 관계로 일단 모든 샘플링 수준은 지정한 체 사용했고
쓰레드를 각각 할당했더니 멀티 사운드 동작도 무리 없었다. 다만 버퍼링을 위한 속도 저하가
좀 걸리지만 큰 무리는 없었다. OpenAL 이 완벽하게 구현되기 전까지만 사용할 예정이라

일단 여기서 멈추었는데 중요한 부분은 오디오트랙은 구간 설정 종료 구간 설정과 같은 부분에
사용되는 frames 의 기준이 매우 이해 어려웠다. 이에 확인한 바로는 대부분이

play 이후 바로 write로 버퍼를 채우는 것이 외국의 사례였다.
쓰레드의 보완을 위해 sleep을 5정도 주는 경우가 그나마 어느정도 부담을 덜지만
flush는 사용을 아예 안한다. flush쓰면 설정된 트랙의 구간 지정 정보가 날아가 버린다.

오디오트랙의 약점이라고 한다면 역시 pcm, wav 타입만 플레이 가능하다는 것이다.
mp3 디코딩과 관련된 클래스를 아직 찾지 못했고 일부 native 라이브러리가 있지만 역시
OPENAL 나오면 또 바뀌어야 해서 사용은 안하고 있다.

사용자 삽입 이미지

괴롭괴롭 디코더 좀 쓰게 해주지 openmax는 까다롭다고... 이미지는 안드로 걸 안드로이드가 남성으로만 나와서 여성으로 만들어 봤다. 우흐하

public void run() {

            int size;
            try {
                size = context.getResources().openRawResource(resid).available();
                InputStream is = context.getResources().openRawResource(resid);
                DataInputStream dis = new DataInputStream(is);

                frequency = AudioTrack.getMinBufferSize(44100, AudioFormat.CHANNEL_CONFIGURATION_STEREO,
                AudioFormat.ENCODING_PCM_16BIT);
                byte[] buffer = new byte[frequency];

                track.reloadStaticData();
                track.play();
                state = 1;
                Log.d("track Run"+size,track.getPlayState()+"__"+track.getNotificationMarkerPosition());
                float Streanvolume = mAudioManager.getStreamVolume(AudioManager.STREAM_NOTIFICATION);
                Streanvolume  = Streanvolume / (mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC));
                track.setStereoVolume(Streanvolume, Streanvolume);
                while(dis.available()>0)
                {
                    size = dis.read(buffer);
                    if(size<8000)
                        break;
                    track.write(buffer, 0, size);
                    //Log.d("track buff",size+"__"+dis.available()+" ___"+track.write(buffer, 0, size));
                    Thread.sleep (5) ;
                    //track.flush();
                }
                //state = 0;
                //track.stop();
                dis.close();
                dis = null;
                buffer = null;
            } catch (Exception ex) {
                Log.d(Jsound.class.getName(),ex+"__");
                //Logger.getLogger(Jsound.class.getName()).log(Level.SEVERE, null, ex);
            }
            finally{
                state = 0;
                track.stop();
            }
        }

지금은 리소스를 그 때 그 때 읽어서 쓰지만 속도가 너무 느리다고 판단되면 버퍼를 운용할 생각이다.
안드로이드 아직 길이 멀다.

www.gamehon.com www.gamemotor.com