Embedded Linux] wavplay - O_NONBLOCK 모드

wavplay 소스를 참고하여 wav 파일을 재생시키는데 정지시 사운드 카드를 close 할때 적지않은 딜레이가 발생하였다.

버튼을 눌러 재생/정지를 반복하는데 그런 딜레이는 문제가 될 여지가 많다.

그렇다고 하면 Non-Blocking 모드를 이용해보자.

    int fd = open("dev/dsp", O_WRONLY | ONONBLOCK);
    
    // wav파일을 열고 
    // 파일을 read
    // 장치에 write
    참고 : http://forum.falinux.com/zbxe/?document_srl=406370 

 이런식으로 하면 잘될거 같지만... 그렇지 않다. 
    
 파일이 일정시간 재생이 된 후 끊겨 버린다.
 재생을 아랑곳하지 않고 read -> write를 하니 사운드버퍼가 찼을때는 write를 못하는 것이다.

 따라서 write시에 사운드 카드를 체크해야 한다. 

    int get_writable_size()
    {
        audio_buf_info   bi;

        ioctl(fd_soundcard, SNDCTL_DSP_GETOSPACE, &bi);

        return bi.bytes;
    }
    
    writable_len = get_writable_size();
    if( writable_len > read_size )
    {
       write(fd, buff, read_size);
    }

그리고 interrupt 시엔 사운드 버퍼를 리셋하자.

    ioctl(fd_soundcard, SNDCTL_DSP_RESET, NULL);
    ioctl(fd_soundcard, SNDCTL_DSP_SYNC);

마지막으로 하나가 더 남았는데 interrupt는 다른 스레드에서 발생하기 때문에 자칫하면 에러가 발생할 수 있다.
따라서 write시와 reset시 MutexLock을 한다.

    // 쓰기
    MutexLock();
    write(fd, buff, read_size);
    MutexUnLock();
    
    // 종료
    MutexLock();
    ioctl(fd_soundcard, SNDCTL_DSP_RESET, NULL);
    ioctl(fd_soundcard, SNDCTL_DSP_SYNC);
    MutexUnLock();

이렇게 해서 버튼 동작으로 재생/정지를 딜레이 없이 구현할 수 있었다.


ps. alsa를 이용하여 재생시에는 딜레이 없이 정지된다. 내부적으로 non-block모드를 이용하는지는 체크해봐야 한다.

by 이카로스 | 2010/06/10 13:35 | Linux | 트랙백 | 덧글(0)

트랙백 주소 : http://icarosss.egloos.com/tb/2621355
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]

:         :

:

비공개 덧글

<< 이전 페이지     다음 페이지 >>