Statistics

Members: 1925
News: 293
Web Links: 1
Visitors: 3826358

Who's Online

Damn Vulnerable LinuxDamn Vulnerable Linux (DVL) is a Linux-based (modified Damn Small Linux) tool for IT-Security & IT-Anti- Security and Attack & Defense. [CLICK HERE FOR MORE INFOS! ]

Featured Conference Video

T16-Recon2006-Joe_Stewart-OllyBonE.gif OllyBone - Semi-Automatic Unpacking on IA-32. View the conference video here!
Home arrow About/Disclaimer
Using the audio device under Linux
User Rating: / 0
PoorBest 
Written by Karsten Scheibler   


The example code below is very simple. It doesn't check if your soundcard supports the options required (44.1 kHz mono/stereo 16 Bits signed). This causes wrong output if your soundcard doesn't support this. Of course your kernel has to have loaded the correct driver for your soundcard in order to get this work.
Remark (a):
Save this page as audio.html and use the following command to extract the source code with a sample Makefile:
sh -c "( mkdir audio && cd audio && awk '/^<!--eof/{d=0}{if(d)print>f}/^<!--sof/{f=\$2;d=1}' ) < audio.html"
Remark (b):
Some browsers try to be super smart and reformat the html code so you may have trouble to extract the files. This is the right time to learn more about wget, a tool to download files via http or ftp ;-)
Remark (c):
Some versions of nasm are known to generate broken code. I have used nasm-0.98 for this example which worked for me.

This is a short explanation how you can use the OSS interface of the kernel to output audio samples. If you find mistakes or have suggestions, mail This e-mail address is being protected from spam bots, you need JavaScript enabled to view it .

The example code below is very simple. It doesn't check if your soundcard supports the options required (44.1 kHz mono/stereo 16 Bits signed). This causes wrong output if your soundcard doesn't support this. Of course your kernel has to have loaded the correct driver for your soundcard in order to get this work.

short procedure:

  1. open the device via sys_open (usually /dev/dsp)
  2. set your audio options via sys_ioctl
  3. use sys_write to output the audio samples

Mostly all of the ioctl's used here are read/write this means the address given in edx must be writable, because the kernel writes the real parameter for your sound options back to this address (if you want to set 48 kHz but your soundcard only supports 44.1 kHz you will find this value in your variable addressed with edx). Therefore placing such a variable in section .text is a bad idea. Notice: if you look at the kernel sources (especially /usr/src/linux/include/linux/soundcard.h) you will find multiple names for the same ioctl (example: SNDCTL_DSP_CHANNELS is equal to SOUND_PCM_WRITE_CHANNELS).

If you want to use sound output in your program you should do something more than this sample code. Here some more interesting ioctl's:

  • check SNDCTL_DSP_GETBLKSIZE how many data you have to write to your soundcard, before playing starts (the value should be in bytes). If you write less than this to the audio device no output will be earable. Remember: samples already in the buffer also count.
  • use SNDCTL_DSP_GETODELAY to check how many bytes (NOT SAMPLES!!) are currently in the output buffer
  • perhaps you have to use SNDCTL_DSP_NONBLOCK to make writes (smaller than the DMA buffer) nonblocking.
  • while using SNDCTL_DSP_SETFMT, SNDCTL_DSP_CHANNELS and SNDCTL_DSP_SPEED don't forget to check the values the kernel gives you back.
  • use SNDCTL_DSP_SETFRAGMENT to set the granularity of DMA buffer. If i remember right, this influences also the amount of generated IRQs by the soundcard. The higher the granularity the higher the latency and the lower the number of generated IRQs.

It is always a good idea to write as much data as possible at once, because every syscall consumes extra cpu cycles.

The sample code below makes 2 outputs. First a simple sawtooth waveform and second it tries to open the file audio.raw and if it exists it is played. This file should be in the format 44.1 kHz, stereo, 16 Bit signed.


;****************************************************************************
;****************************************************************************
;*
;* USING THE AUDIO DEVICE UNDER LINUX
;*
;* written by Karsten Scheibler, 2003-DEC-08
;*
;****************************************************************************
;****************************************************************************
global audio_start
;****************************************************************************
;* some assign's
;****************************************************************************
%assign SYS_READ			3
%assign SYS_WRITE			4
%assign SYS_OPEN			5
%assign SYS_IOCTL			54
%assign O_RDONLY			0
%assign O_RDWR				2
%assign SNDCTL_DSP_RESET		0x00005000
%assign SNDCTL_DSP_SPEED		0xc0045002
%assign SNDCTL_DSP_SETFMT		0xc0045005
%assign		AFMT_S16_LE		0x00000010
%assign SNDCTL_DSP_CHANNELS		0xc0045006
%assign AUDIO_DATA_SIZE			0x100000	;1 MB
;****************************************************************************
;* data
;****************************************************************************
section .data
align	4
audio_handle:				dd	0
ioctl_table:				dd	SNDCTL_DSP_RESET, 0
dd	SNDCTL_DSP_SPEED, 44100
dd	SNDCTL_DSP_CHANNELS, 1
dd	SNDCTL_DSP_SETFMT, AFMT_S16_LE
section .bss
alignb	4
audio_data:				resb	AUDIO_DATA_SIZE
;****************************************************************************
;* audio_start
;****************************************************************************
section .text
audio_start:
;open the device
mov	dword eax, SYS_OPEN
mov	dword ebx, .device
mov	dword ecx, O_RDWR
int	byte  0x80
test	dword eax, eax
js	near  audio_error
mov	dword [audio_handle], eax
;set the options: 44.1 kHz, mono, 16 Bit signed
xor	dword ebp, ebp
.do_ioctl:
mov	dword eax, SYS_IOCTL
mov	dword ebx, [audio_handle]
mov	dword ecx, [ioctl_table + 8 * ebp]
lea	dword edx, [ioctl_table + 8 * ebp + 4]
int	byte  0x80
test	dword eax, eax
js	near  audio_error
inc	dword ebp
cmp	dword ebp, byte 4
jb	short .do_ioctl
;output something very simple (sawtooth waveform)
;not recommended: write every single sample like here
mov	dword esi, 0x40000
xor	dword ebp, ebp
.loop:
mov	word  [audio_data], bp
mov	dword eax, SYS_WRITE
mov	dword ebx, [audio_handle]
mov	dword ecx, audio_data
mov	dword edx, 2
int	byte  0x80
test	dword eax, eax
js	near  audio_error
add	dword ebp, 0x0100
dec	dword esi
jnz	short .loop
;open a raw audio file
;format should be 44.1 kHz, stereo, 16 Bit signed
mov	dword eax, SYS_OPEN
mov	dword ebx, .file
mov	dword ecx, O_RDONLY
int	byte  0x80
mov	dword ebx, eax
test	dword eax, eax
js	short audio_error
mov	dword eax, SYS_READ
mov	dword ecx, audio_data
mov	dword edx, AUDIO_DATA_SIZE
int	byte  0x80
test	dword eax, eax
js	short audio_error
;set output to stereo
lea	dword ebp, [ioctl_table + 4 * 6]
mov	dword eax, SYS_IOCTL
mov	dword ebx, [audio_handle]
mov	dword ecx, SNDCTL_DSP_CHANNELS
mov	dword [ebp], 2
mov	dword edx, ebp
int	byte  0x80
test	dword eax, eax
js	short audio_error
;dump it to the audio device
mov	dword eax, SYS_WRITE
mov	dword ebx, [audio_handle]
mov	dword ecx, audio_data
mov	dword edx, AUDIO_DATA_SIZE
int	byte  0x80
test	dword eax, eax
js	short audio_error
;exit nicely
jmp	short audio_end
.device:				db	"/dev/dsp", 0
.file:					db	"audio.raw", 0
;****************************************************************************
;* audio_error
;****************************************************************************
section .text
audio_error:
xor	dword eax, eax
inc	dword eax
mov	dword ebx, eax
int	byte  0x80
;****************************************************************************
;* audio_end
;****************************************************************************
section .text
audio_end:
xor	dword eax, eax
xor	dword ebx, ebx
inc	dword eax
int	byte  0x80
;*********************************************** 
 This e-mail address is being protected from spam bots, you need JavaScript enabled to view it
  *