OS Lab 14 Eng
OS Lab 14 Eng
Методичні вказівки
до курсу “Операційні системи”
для студентів базової вищої освіти
за напрямком “Комп’ютерні науки”
Львів - 2022
Laboratory work #14
Topic – Multimedia system functions.
The goal is to learn the basic principles of sound card operation and
related basic system functions.
THEORETICAL PROVISIONS
Most people buy computers for entertainment (US statistics). An
entertaining program becomes when, in addition to the intellectual activity
of a person, it also engages his emotional activity. Entertainment software
uses games, positive news, communication, drawing, writing poetry and
music, free imagination, association and guesswork. Theoretically, for
productive work, each user himself determines his emotional spectrum,
which he needs to accumulate his intellectual or physical energy.
Developers of software systems must take these obvious things into
account and maintain the emotional state of their users in the proper
working tone. This can be done, for example, with the help of sounds. If
various sounds are associated with various software situations, the user will
be better oriented in them and make decisions faster. In any case, the sounds
should not interfere and be played very quietly. If a certain program
situation is repeated many times, then the sound should be removed in
general to give the user the opportunity to calmly (in silence) consider his
decision.
A sound card on a computer is capable not only of playing sounds, but
also of inputting and recording them in a given memory buffer. Therefore, it
is possible to develop software that uses microphone input. Theoretically,
instead of a microphone, you can connect any analog signal source, for
example, a pressure transducer, an electrocardiograph, or an ordinary
inductor. Two mutually perpendicular coils can be used as a metal detector -
a signal is applied to one of them, and a signal is read from the other. The
presence of metal near the coils significantly increases the level of the
received signal. If you use the 16-bit sound mode, the computer will be able
to distinguish very weak signals.
A separate area of multimedia is system functions for creating video
files, as well as for their compression and decompression. It is possible to
create systems for generating video clips according to a certain scenario in
the form of a specialized programming language. This will make it possible
to create high-quality multimedia lectures, or conveniently adjust existing
video material, as well as create images for a given musical composition.
Presentation of such a video using a specialized language will be the most
compressed form of its presentation.
WORK PERFORMANCE PROCEDURE
So, a sound card is a specialized controller for playing and receiving
sound signals. It has its own local memory and a specialized (signal)
processor that works with the local memory in which part of the sound
fragment is located. Therefore, playing or receiving sound occurs in parallel
with the work of the central processor. When the signal processor finishes
processing an audio fragment that is in local memory, it sends an interrupt
request to the CPU (via the interrupt controller), after which the interrupt
processing subsystem must "push" (or "pick up") the next data fragment
using the appropriate interrupt handler.
To display sound data, try running the following program. Note that
there is one important feature of functions that work directly with drivers:
the data buffer used by the driver must always start at an even address, or
the function may not work. Data areas ".data" and ".data?" always start with
even addresses.
In the program, the DEVICE_INDEX variable indicates the index of
the audio device. For example, if the computer has a standard integrated
audio card, then the values of this variable can be 0 or –1 (0FFFFFFFFh),
but if a WEB camera is connected to the computer that has a built-in
microphone, then –1 means an integrated audio card , and 0 is the
microphone in the WEB camera.
.586
.model flat,stdcall
extrn ExitProcess:Proc, waveInOpen:Proc, waveInClose:Proc, waveInStart:Proc
extrn waveInPrepareHeader:Proc, waveInAddBuffer:Proc, MessageBoxA:Proc
extrn GetDC:Proc, FillRect:Proc, LineTo:Proc, ReleaseDC:Proc,
InvalidateRect:Proc
extrn GetModuleHandleA:Proc, CreateWindowExA:Proc, CreatePen:Proc,
SelectObject:Proc
CALLBACK_FUNCTION equ 30000h
WIM_DATA equ 3C0h
WAVE_FORMAT_PCM equ 1
WS_VISIBLE equ 010000000h
WS_THICKFRAME equ 40000h
.data
WAVEFORMATEX: ; WAV audio data format block
Tag dw WAVE_FORMAT_PCM ; analog to digital converter
nChannels dw 1
SampleRate dd 176400
BytesPerSec dd 176400*2
BlockAllign dw 2
BitsPerSample dw 16
dw 0 ; WFX_EXTRA_BYTES
WAVEHDR: ; Data buffer header
lpData dd offset buffer ; buffer address (even)
dwBufferLength dd 700*2 ; buffer length
dwBytesRecorded dd 0 ; the number of bytes written
dwUser dd 0
dwFlags dd 0
dwLoops dd 0 ; number of retries on output
lpNext dd offset WAVEHDR ; pointer to the next data header
reserved dd 0
sizeof_WAVEHDR dd 8*4 ; header length
WaveIn dd 0 ; handler of the device
txt db 'Stop Process',0
hdc dd 0 ; graphic context for drawing lines
RECT: ; background rectangle:
X dd 0
Y dd 0
W dd 600
H dd 500
DEVICE_INDEX dd -1 ; The device is selected by default
hApp dd 0
CLASSNAME db "ListBox",0 ; used window class
NewHWnd dd 0
hPen dd 0
TITLE1 db " An example of working with a microphone ",0
.data?
buffer db 10000 dup(?) ; audio buffer
;================================================
.CODE
Start: call CreatePen,0,3,0ffh
mov hPen,eax
call GetModuleHandleA,0
mov hApp,eax
push 0
push hApp
push 0
push 0
push H
push W
push 50
push 50
push WS_VISIBLE or WS_THICKFRAME
push offset TITLE1
push offset CLASSNAME
push 0
call CreateWindowExA
mov NewHWnd,eax
call waveInOpen, offset WaveIn,DEVICE_INDEX, offset
WAVEFORMATEX, offset waveInProc,hApp,CALLBACK_FUNCTION
call waveInPrepareHeader, WaveIn, offset WAVEHDR,
sizeof_WAVEHDR
call waveInAddBuffer, WaveIn, offset WAVEHDR , sizeof_WAVEHDR
call waveInStart, WaveIn
call MessageBoxA,0,offset txt,offset txt,0
call waveInClose,WaveIn
call InvalidateRect,0,offset RECT,1
STOP: call ExitProcess,0
.586
.model flat, stdcall
Extrn GetModuleHandleA:Proc, MessageBoxA:Proc, mciSendStringA:Proc,
ExitProcess:Proc, waveInOpen:Proc, waveInClose:Proc, waveInStart:Proc,
waveInPrepareHeader:Proc, waveInAddBuffer:Proc
extrn CreateFileA:Proc,WriteFile:Proc,CloseHandle:Proc
WAVE_MAPPER equ -1
WAVE_FORMAT_PCM equ 1
.data
ERR_TXT db "ERROR of WaveInOpen",0
WAVEFORMATEX:
Tag dw WAVE_FORMAT_PCM
nChannels dw 1
SampleRate dd 44100
BytesPerSec dd 44100*2
BlockAllign dw 2
BitsPerSample dw 16
dw 0 ; WFX_EXTRA_BYTES
WAVEHDR:
ADR_AUDIO_DATA dd offset buffer
dwBufferLength dd 20000000
WAV_DATA_LEN dd 0
dwUser dd 0
dwFlags dd 0
dwLoops dd 0
lpNext dd offset WAVEHDR
reserved dd 0
sizeof_WAVEHDR dd 8*4
WaveIn dd 0
TEXT_STOP db "STOP...",0
TEXT_CREATE_WAV db "Recording: "
Wav_FileName db "MIC.Wav",0
play_MCI db "play MIC.Wav wait",0
.data?
buffer db 20000000 dup(?)
;=============================================
.code
Start:
call MICROPHONE_ON
call MessageBoxA,0,offset TEXT_CREATE_WAV,offset TEXT_STOP,0
call waveInClose,WaveIn
;--------------------------
include Save_WAV.txt
;--------------------------
call mciSendStringA,offset play_MCI,0,0,0
STOP: call ExitProcess,0
;-------------------------------------
MICROPHONE_ON:
call GetModuleHandleA,0
call waveInOpen,offset WaveIn,WAVE_MAPPER,offset
WAVEFORMATEX,0,eax,0
call waveInPrepareHeader, WaveIn, offset WAVEHDR,
sizeof_WAVEHDR
call waveInAddBuffer, WaveIn, offset WAVEHDR , sizeof_WAVEHDR
call waveInStart, WaveIn
ret
end Start
Most audio files that can be downloaded from the Internet are
compressed in mp3 format. To convert formats in the operating system,
there is a function acmStreamConvert.
In the next task, you will need to decompress any downloaded file into
WAV format and play the decompressed sound file. Before using this
function, you need to open a stream to convert one audio data to another
using acmStreamOpen. The parameters of this function are the input and
output file formats. Each audio data format is described by a specific
WAVEFORMATEX structure. The appearance of this structure was
described for WAV files in the previous examples. In the following
example you will find a description of this structure for compressed mp3
files. In the documentation, it is officially called
MPEGLAYER3WAVEFORMAT. So, compile the following program and
convert file 1.mp3 to file 1.wav:
.586
.model flat,stdcall
Extrn ExitProcess:proc, MessageBoxA:Proc, _wsprintfA:Proc
Extrn acmStreamOpen:Proc, acmStreamSize:Proc,
acmStreamPrepareHeader:Proc, acmStreamConvert:Proc,
acmStreamUnprepareHeader:Proc, acmStreamClose:Proc
Extrn CreateFileA:Proc, GetFileSize:Proc, GlobalAlloc:Proc, GlobalLock:Proc,
ReadFile:Proc, CloseHandle:Proc
Extrn GlobalUnlock:Proc, GlobalFree:Proc, lstrlen:Proc, WriteFile:Proc
GENERIC_WRITE equ 40000000h
GENERIC_READ equ 80000000h
OPEN_EXISTING equ 3
GMEM_MOVEABLE equ 2
.data
openname_MP3 db "1.mp3",0 ; audio file name
hFile_MP3 dd 0
File_Size_MP3 dd 0
HGlobal_MP3 dd 0
ADR_BEGIN_FILE_MP3 dd 0
TMP_SizeRead dd 0
.code
Start:
;----------------------------- Open the audio mp3 file:
push 0
push 0
push OPEN_EXISTING
push 0
push 1
push GENERIC_READ
push offset openname_MP3
call CreateFileA
mov hFile_MP3,eax
;--------------------------------------------- report the error if there is one
cmp hFile_MP3,-1
jnz C_FILE_MP3_OK1
ERR_FILE_MP3:
call MessageBoxA,0,offset TEXT_ERR_FILE_MP3,offset
openname_MP3,10h
jmp STOP
TEXT_ERR_FILE_MP3 db "Audio File is not Loaded!",0
C_FILE_MP3_OK1:
;----------------------------------------------------------- we read the audio mp3 file:
call GetFileSize,hFile_MP3,0
mov File_Size_MP3,eax
call GlobalAlloc, GMEM_MOVEABLE, File_Size_MP3
mov HGlobal_MP3,eax
call GlobalLock,eax
mov ADR_BEGIN_FILE_MP3,eax
call ReadFile, hFile_MP3, ADR_BEGIN_FILE_MP3, File_Size_MP3, offset
TMP_SizeRead, 0
mov eax,File_Size_MP3
cmp eax,TMP_SizeRead
jnz ERR_FILE_MP3
call CloseHandle,hFile_MP3
;----------------------------------------------------
ACM_STREAMOPENF_NONREALTIME equ 4
ACM_STREAMSIZEF_SOURCE equ 0
ACM_STREAMCONVERTF_START equ 10h
ACM_STREAMCONVERTF_END equ 20h
WAVE_FORMAT_MPEGLAYER3 equ 55h
MPEGLAYER3_WFX_EXTRA_BYTES equ 12
MPEGLAYER3_ID_MPEG equ 1
.data
MPEGLAYER3WAVEFORMAT: ; mp3 audio data format block
dw WAVE_FORMAT_MPEGLAYER3
dw 2
dd 44100
dd 40000
dw 1
dw 0
dw MPEGLAYER3_WFX_EXTRA_BYTES
dw MPEGLAYER3_ID_MPEG
dd 2 ; flags 4
dw 1500 ; nBlockSize = 144 x (bitrate / sample rate) + padding
dw 1 ; nFramesPerBlock
dw 0 ; nCodecDelay
;-----------------------------
HGlobal_WAV dd 0
HSTREAM dd 0
;-----------------------------
WAVEFORMATEX: ; WAV audio data format block
dw 1 ; Format Tag
nChannels dw 2
SampleRate dd 44100
BytesPerSec dd 44100*4
BlockAllign dw 4
BitsPerSample dw 16
dw 0 ; WFX_EXTRA_BYTES
;--------------------------------
ACMSTREAMHEADER: ; header for the transcoding stream
dd 84
FLG dd 0
dd 0
ADR_SOURCE_DATA_BUFFER dd 0
LEN_SOURCE_DATA_BUFFER dd 0
dd 0
dd 0
ADR_OUTPUT_DATA_BUFFER dd 0
OUTPUT_LEN dd 0
OUTPUT_REAL_LEN dd 0
dd 12 dup(0)
;---------------------------------------------- We open the stream for transcoding:
.code
call acmStreamOpen, offset HSTREAM,0,offset
MPEGLAYER3WAVEFORMAT,offset
WAVEFORMATEX,0,0,0,ACM_STREAMOPENF_NONREALTIME
cmp eax,0
jnz ERR_FILE_MP3
call acmStreamSize, HSTREAM, File_Size_MP3, offset OUTPUT_LEN,
ACM_STREAMSIZEF_SOURCE
cmp eax,0
jnz ERR_FILE_MP3
; We fill in the ACMSTREAMHEADER structure to control this stream:
mov eax,ADR_BEGIN_FILE_MP3
mov ADR_SOURCE_DATA_BUFFER,eax
mov eax,File_Size_MP3
mov LEN_SOURCE_DATA_BUFFER,eax
call GlobalAlloc, GMEM_MOVEABLE, OUTPUT_LEN
mov HGlobal_WAV,eax
call GlobalLock,eax
mov ADR_OUTPUT_DATA_BUFFER,eax
call acmStreamPrepareHeader, HSTREAM, offset
ACMSTREAMHEADER,0
cmp eax,0
jnz ERR_FILE_MP3
;-------------------------------------- We start transcoding:
call acmStreamConvert, HSTREAM, offset ACMSTREAMHEADER,
ACM_STREAMCONVERTF_START or ACM_STREAMCONVERTF_END
cmp eax,0
jnz ERR_FILE_MP3
call acmStreamUnprepareHeader, HSTREAM, offset
ACMSTREAMHEADER,0
call acmStreamClose,HSTREAM,0
; We create the header of the WAV file and write the transcoded data to the file:
.data
Wav_FileName db "1.wav",0
ADR_AUDIO_DATA dd 0 ; audio data address for recording the file
WAV_DATA_LEN dd 0
.code
mov eax,ADR_OUTPUT_DATA_BUFFER
mov ADR_AUDIO_DATA,eax
mov eax, OUTPUT_REAL_LEN ; the actual length of the sound
mov WAV_DATA_LEN, eax
;-------------------------------------- Save the result from the memory block to a file:
include Save_WAV.txt
;------------------ We play the directly received sound WAV buffer:
Extrn waveOutOpen:Proc, waveOutPrepareHeader:Proc, waveOutWrite:Proc,
waveOutClose:Proc, waveOutReset:Proc
WHDR_BEGINLOOP equ 4h
WHDR_ENDLOOP equ 8h
.data
hDEV dd 0
WAVEHDR1:
lpData1 dd 0 ; buffer address (even)
dwBufferLength1 dd 0 ; buffer length
dwBytesRecorded1 dd 0
dwUser1 dd 0
dwFlags1 dd WHDR_BEGINLOOP or WHDR_ENDLOOP ;
тип буферу
dwLoops1 dd 0FFFFFFFFh
lpNext1 dd offset WAVEHDR1
reserved1 dd 0
sizeof_WAVEHDR dd 8*4
.code
mov eax,ADR_OUTPUT_DATA_BUFFER
mov lpData1,eax
mov eax,OUTPUT_REAL_LEN
mov dwBufferLength1,eax
call waveOutClose,hDEV
call waveOutOpen, offset hDEV,-1, offset WAVEFORMATEX,0,0,0
call waveOutPrepareHeader, hDEV, offset WAVEHDR1,
sizeof_WAVEHDR
call waveOutWrite, hDEV, offset WAVEHDR1, sizeof_WAVEHDR ;
озвучити буфер
call MessageBoxA,0,offset Wav_FileName,offset openname_MP3,0
STOP: call GlobalUnlock,HGlobal_WAV
call GlobalFree,HGlobal_WAV
call GlobalUnlock,HGlobal_MP3
call GlobalFree,HGlobal_MP3
call ExitProcess,0
end Start
.586
.model flat,stdcall
extrn ExitProcess :Proc
extrn AVIFileInit :Proc
extrn AVIFileOpenA :Proc
extrn AVIFileGetStream :Proc
extrn AVIStreamGetFrameOpen :Proc
extrn AVIStreamGetFrame :Proc
extrn AVIStreamGetFrameClose :Proc
extrn AVIStreamRelease :Proc
extrn AVIStreamGetFrameClose :Proc
extrn ShellExecuteA :Proc
AVIGETFRAMEF_BESTDISPLAYFMT =1
BITMAPINFO_SIZE = 40
.data
AVIFILEHANDLE dd 0
AVI_File_Name db "new.avi",0 ; "Snowboard.avi",0
AVISTREAM dd 0
FRAME_NUMBER dd 50 ; any value
hFrame dd 0
;-----------------------------
FileHeader dw 4d42h ; 'BM'
BMsizedd 0 ; BMsize = biSizeImage+54
dd 0
HeaderSize dd 54 ; file header length
BITMAPINFOHEADER_SIZE dd 0
IMAGE_SIZE dd 0
;-----------------------------
.code
Start: call AVIFileInit
call AVIFileOpenA,offset AVIFILEHANDLE,offset AVI_File_Name,0,0
CALL AVIFileGetStream,AVIFILEHANDLE,offset AVISTREAM,'sdiv',0
LOOP1:
CALL
AVIStreamGetFrameOpen,AVISTREAM,AVIGETFRAMEF_BESTDISPLAYFMT
mov hFrame,eax
CALL AVIStreamGetFrame,eax,FRAME_NUMBER ; IGetFrame
cmp eax,0
jz STOP
mov ADR_FRAME_DATA,eax
mov esi,eax ; addr of BitmapinfoHeader
mov eax,[esi]
mov BITMAPINFOHEADER_SIZE,eax
add eax,14
mov HeaderSize,eax
mov eax,[esi+20]
mov IMAGE_SIZE,eax
add eax,HeaderSize
mov BMsize,eax
;---------------------------------------------------------------------------------------------
Extrn CreateFileA:proc, WriteFile:proc, CloseHandle:proc
GENERIC_WRITE equ 40000000h
CREATE_ALWAYS equ 2
FILE_ATTRIBUTE_NORMAL equ 80h
.data
FileName DB 'FRAME.bmp',0 ; outputting file
hFile dd 0
TMP_Written dd 0
ADR_FRAME_DATA dd 0
.code
call CreateFileA,offset FileName,
GENERIC_WRITE,0,0,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0
mov hFile,eax
; write a BMP-file header:
call WriteFile, hFile, offset FileHeader, 14, offset TMP_Written, 0
; write color data:
mov eax,BITMAPINFOHEADER_SIZE
add eax,IMAGE_SIZE
call WriteFile, hFile, ADR_FRAME_DATA, eax, offset TMP_Written, 0
call CloseHandle, hFile
;--------------------------------------------------------------------
call AVIStreamGetFrameClose,hFrame
call ShellExecuteA,0,0,offset FileName,0,0,1 ; Show image
STOP: call ExitProcess,0
end Start
CONTROL QUESTIONS
1. What is multimedia?
2. What multimedia functions do you know?
3. What is a data stream?
4. How do multimedia functions use the concept of streams?
5. How does the audio card work?