A viewer for .wav files

Click here to load reader

download A viewer for .wav files

of 24

  • date post

  • Category


  • view

  • download


Embed Size (px)


A viewer for .wav files. On using some CRTC registers to simulate horizontal scrolling through a large data-file. ‘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. - PowerPoint PPT Presentation

Transcript of A viewer for .wav files

  • A viewer for .wav filesOn using some CRTC registers to simulate horizontal scrolling through a large data-file

  • waveviewWe 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

  • VESA Display ModeWe selected our SuperVGA display mode: pixel-resolution: 1024-by-768color-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

  • Vertical bandsWe focus on unsigned 8-bit pulse-codesThese values range from 0 to 255 (=0xFF)The mid-value (0x80) represents silenceFor pulse-codes above 0x80 we will draw an upward band, for pulse-codes below 0x80 we will draw a downward bandsilence = 0x800xFF0x00

  • How to draw a band int ymin = (vres256)/2, ymax = ymin+256; intpcm = 255 - wavedata[ x ]; for (int y = ymin; y < ymax; y++){if (((y=0x80)))vram[ y * hres + x ] = fgcolor;elsevram[ y * hres + x ] = bgcolor;}

  • 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 users address-spaceThis would make it possible to avoid any memory-allocation calls, or repetitious forward and backward lseek() operations, as our user scrolls through the files data

  • Pre-computing our imageDuring development, however, we decided to pre-compute the very large graphical image, storing it in memory allocated from our programs heap using the calloc() call This reduced the amount of computation that had to be done during view scrollingBut it requires us to set up some machinery for keeping track of a large pre-computed virtual image and the much smaller visible image

  • Screen as a moving windowVirtual image (too big to see all at once)Visual image(limited by screens width)srcminsrcmaxsrcnowVRAM User can shift the window left or right using arrow-keys screen-width

  • Scrolling was slowDuring development we discovered that our plan for horizontal scrolling was just not fast enoughSo we tweaked it by making use of two of the CRT Controllers hardware registers:The CRTC_PITCH register The CRTC_START register Access is Radeon-specific (non-portable)

  • The pitch concept Pixel-values are arranged linearly by rowsThe 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 pitchBut this pitch is a programmable value We decided to double its value, so every scanline would be twice its normal length

  • Initial image relationshipsApparent image on display screen is 1024-by-768Actual image in VRAM is 2048-by-768CRTC_PITCHVRAM This part of the VRAM image is not currently being displayed 768scanlinesCRTC_START

  • After user hits right-arrowApparent image on display screen is 1024-by-768Actual image in VRAM is 2048-by-768CRTC_PITCHVRAMThese parts of the VRAM image are not currently being displayed 768scanlinesCRTC_START

  • Illusion of a full-file imageWe want the user to believe theres a total continuous horizontal image of all the .wav files 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 screens limited width)

  • The reality is differentBut our VRAM is limited in size (16MB), so theres 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 VRAMWe want rapid -- and smooth scrolling whenever the user hits right or left arrow

  • So heres how we do itHEAP-MEMORYVRAM-MEMORYsrcminsrcmaxsrcnowdstmindstmaxdstnowFull pre-computed imagePart of the image now visibleCRTC_STARTWhen 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

  • We also prepare for restartingEach 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, well have two totally identical images So a user wont notice if CRTC_START is reset

  • No visible effectCRTC_START With repeated left and right images in VRAM, there will be no perceptible change in whats seen when the CRTC_START register is changed from dstmax to dstmindstmindstmaxdstnow

  • Any improvements?After we wrote waveview.cpp, we realized that an improvement could readily be made, merely by changing a few lines of our codePresently 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

  • Busy-waiting is wastefulBut 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

  • 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 interimBy calling the nanosleep() function we can put our task to sleep for 1/60 seconds (i.e. for 16666667 nanoseconds)

  • Programming details #include // for nanosleep() struct timespec ts = { 0, 16666667 };

    nanosleep( &ts, NULL );

    // see the man page if you want more info

  • In-class exercise #1See 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?

  • In-class exercise #2Presently the waveview tool scrolls the displayed image by 8-pixels, right or left, each time the user hits these arrow-keysCan 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

  • In-class exercise #3Can 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)?