Download presentation
Presentation is loading. Please wait.
1
A viewer for.wav files On using some CRTC registers to simulate horizontal scrolling through a large data-file
2
‘waveview’ We recorded brief samples of our voices We saved the waveform data in.wav files Now we consider how to create a useful tool for viewing that sound data graphically
3
VESA Display Mode We selected our SuperVGA display mode: –pixel-resolution: 1024-by-768 –color-depth: 8 bits-per-pixel (256 colors) Color-depth was selected for programming ease (simple to compute pixel-addresses) Pixel-resolution was a ‘trade-off’ between showing lots of data simultaneously and being able to update the screen quickly
4
Vertical ‘bands’ We focus on unsigned 8-bit pulse-codes These values range from 0 to 255 (=0xFF) The mid-value (0x80) represents ‘silence’ For pulse-codes above 0x80 we will draw an upward band, for pulse-codes below 0x80 we will draw a downward band silence = 0x80 0xFF 0x00
5
How to draw a band int ymin = (vres–256)/2, ymax = ymin+256; intpcm = 255 - wavedata[ x ]; for (int y = ymin; y < ymax; y++) { if (((y<=0x80)&&(pcm<=y)&&(y<=0x80)) ||((y>=0x80)&&(pcm>=y)&&(y>=0x80))) vram[ y * hres + x ] = fgcolor; elsevram[ y * hres + x ] = bgcolor; }
6
Using ‘mmap()’ Instead of using the ‘read()’ system-call to transfer the raw waveform data from disk to memory, we elected to use ‘mmap()’ to map the.wav file to user’s address-space This would make it possible to avoid any memory-allocation calls, or repetitious forward and backward ‘lseek()’ operations, as our user scrolls through the file’s data
7
Pre-computing our image During development, however, we decided to ‘pre-compute’ the very large graphical image, storing it in memory allocated from our program’s heap using the ‘calloc()’ call This reduced the amount of computation that had to be done during view ‘scrolling’ But it requires us to set up some machinery for keeping track of a large pre-computed ‘virtual’ image and the much smaller ‘visible’ image
8
Screen as a moving ‘window’ Virtual image (too big to see all at once) Visual image (limited by screen’s width) srcminsrcmaxsrcnow VRAM User can shift the window left or right using arrow-keys screen-width
9
Scrolling was ‘slow’ During development we discovered that our plan for horizontal scrolling was just not fast enough So we ‘tweaked’ it by making use of two of the CRT Controller’s hardware registers: –The CRTC_PITCH register –The CRTC_START register Access is Radeon-specific (non-portable)
10
The ‘pitch’ concept Pixel-values are arranged linearly by rows The separation-distance between any two vertically adjacent pixels is constant (and normally is equal to the length of a visible scanline – this constant is called the ‘pitch’ But this ‘pitch’ is a programmable value We decided to double its value, so every scanline would be twice its normal length
11
Initial image relationships Apparent image on display screen is 1024-by-768 Actual image in VRAM is 2048-by-768 CRTC_PITCH VRAMVRAM This part of the VRAM image is not currently being displayed 768 scan lines CRTC_START
12
After user hits right-arrow Apparent image on display screen is 1024-by-768 Actual image in VRAM is 2048-by-768 CRTC_PITCH VRAMVRAM These parts of the VRAM image are not currently being displayed 768 scan lines CRTC_START
13
Illusion of a full-file image We want the user to believe there’s a total continuous horizontal image of all the.wav file’s pulse-code data available for viewing if the right-arrow key is hit enough times! But only portion of this data can be shown at one time (due to screen’s limited width)
14
The reality is different But our VRAM is limited in size (16MB), so there’s only room for part of the full image However, the full pre-computed image can fit within the enormous Linux heap space, with its parts copied as needed into VRAM We want rapid -- and smooth – scrolling whenever the user hits right or left arrow
15
So here’s how we do it HEAP-MEMORY VRAM-MEMORY srcminsrcmaxsrcnow dstmindstmaxdstnow Full pre-computed image Part of the image now visible CRTC_START When user hits right-arrow, a bit more of the pre-computed image is copied from the heap into VRAM, and then the CRTC_START value is advanced, so the user thinks the screen is scrolling horizontally over the full image
16
We also ‘prepare’ for restarting Each time the view has scrolled rightward, we copy the newly visible vertical bands at the right side of the screen to the region of VRAM which has just gone out-of-view (a relatively small amount of copying time) By the time the screen-image as scrolled to the right-hand half of the VRAM lines, we’ll have two totally identical images So a user won’t notice if CRTC_START is reset
17
No visible effect CRTC_START With repeated left and right images in VRAM, there will be no perceptible change in what’s seen when the CRTC_START register is changed from dstmax to dstmin dstmindstmax dstnow
18
Any improvements? After we wrote ‘waveview.cpp’, we realized that an improvement could readily be made, merely by changing a few lines of our code Presently ‘waveview’ does some ‘busy-waiting’ after it changes the CRTC_START value, to delay drawing to still-visible areas of VRAM until the next vertical retrace cycle has begun This was necessary to prevent our users from seeing those updates to off-screen memory
19
Busy-waiting is wasteful But we could alternatively delay drawing to the still-visible areas of video memory by letting our program ‘sleep’ instead of doing nothing but use up CPU cycles (wasteful!) The sleep time should be quite brief – just long enough to be sure that a new vertical refresh cycle has started, and thus that the new CRTC_START value has taken effect
20
Use ‘nanosleep()’ The screen-refresh rate is approximately 60-frames per second, so if we sleep for 1/60-th of a second, we can be sure that the next refresh-cycle is underway -- and allow other processes to run in the interim By calling the ‘nanosleep()’ function we can put our task to sleep for 1/60 seconds (i.e. for 16666667 nanoseconds)
21
Programming details #include // for nanosleep() struct timespec ts = { 0, 16666667 }; nanosleep( &ts, NULL ); // see the ‘man’ page if you want more info
22
In-class exercise #1 See if you can implement the improvement just discussed – replacing the busy-waiting while-loops with a call to ‘nanosleep()’ Try the experiment of sleeping for a briefer time-interval than 1/60-th second: will you see evidence of flashing screen updates at the right-hand edge (or left-hand edge) of your display screen?
23
In-class exercise #2 Presently the ‘waveview’ tool scrolls the displayed image by 8-pixels, right or left, each time the user hits these arrow-keys Can you easily adjust this pixel-shift size so that the shifts occur in bigger jumps? If not, then decide how the programming could have been done to make this work
24
In-class exercise #3 Can you modify the ‘waveview’ program so that a greater fraction of the.wav data could be viewed on the screen at once? Do you think it would be better to simply omit some of the data (e.g., only showing alternate pulse-codes), or to ‘average’ two consecutive pulse-codes (as we did in an exercise on our midterm exam)?
Similar presentations
© 2024 SlidePlayer.com. Inc.
All rights reserved.