ComputerScientist
174 subscribers
14 photos
3 files
206 links
▜ The Inventor

Stuff that inspire you to create.

See also: ▙ @LitMind
Download Telegram
Approaching is never reaching.

Unless in a discrete reality.
“There are some projects that you keep coming back to as you get more experienced. You make something that you feel proud of, and then three years later you look at it in distaste and feel you could do so much better, so you go for a remake.”
— DrPetter, Raytracers
“Nobody has ever gotten rich making hammers.”
— Rasmus Lerdorf
The problem with doing something no one has ever done before is that you have nothing to compare your work with and measure your progress against.
Where you can, you will bend the logic of the machine to your will; where you can't, your logic will be reshaped by it.
“...[O]ne of the earliest [applications] of dither came in World War II. Airplane bombers used mechanical computers to perform navigation and bomb trajectory calculations. Curiously, these computers (boxes filled with hundreds of gears and cogs) performed more accurately when flying on board the aircraft, and less well on ground. Engineers realized that the vibration from the aircraft reduced the error from sticky moving parts. Instead of moving in short jerks, they moved more continuously. Small vibrating motors were built into the computers, and their vibration was called dither from the Middle English verb "didderen", meaning "to tremble." Today, when you tap a mechanical meter to increase its accuracy, you are applying dither, and modern dictionaries define dither as a highly nervous, confused, or agitated state. In minute quantities, dither successfully makes a digitization system a little more analog in the good sense of the word.”
— Ken Pohlmann, Principles of Digital Audio
Frustum culling

In a game, we want to smooth animations:

Smooth animation = a high, fixed FPS (frames per second)

The GPU, like any other processor, can only do a fixed amount of work in a fixed amount of time.

A fixed FPS = a fixed time to create a frame = a fixed work budget per frame = limited things the GPU has to draws for a frame

The GPU mainly does two jobs:
Vertex shading: related to the 3D geometric description of objects in the scene
Pixel shading: drawing the individual pixels on the frame

We also want high quality images:

Higher image quality = more pixel shading = less vertex shading

To decrease the amount of vertex shading the CPU, which decides what should be drawn and sends them to the GPU, should skip the things outside the view cone.

Because the display is a rectangle, that view cone is a four-sided pyramid that has its point cut off; this is called a "frustum" in geometry.

Frustum cull = have the CPU skip telling the GPU to draw things outside of the viewing frustum

To a very rough approximation, an outdoors scene with a 90-degree view cone sees 1/4 of the full 360 degrees, so if we compare what would happen if we draw the full scene to drawing
only within the view cone, we skip approximately 3/4 of the vertex shading work.

Because of the way the system works, no pixel shading would have been done for culled objects, only vertex shading. So culling saves vertex shader work but not pixel shader work.

Note that frustum culling is not loading or unloading anything from the main memory. The objects still have to be loaded (in RAM) for physics, AI, etc. to be applied to them; they are
just not rendered (not sent to the GPU).

Almost every game and animated clips uses frustum culling, because it is simple, cheap and effective. It is probably the single most ubiquitous optimization found in graphics.

Generally, graphics optimization is important because it frees up GPU time to render more things, with more details. There are many ways of saving work on the GPU, such as:

Frustum culling: not trying to draw things that can't be seen because of the view cone
Occlusion culling: not trying to draw things that can't be seen because they're behind other things
Level of detail: skipping small geometric details when things are far enough away those details can't be made out anyway
• Simpler mathematical approximations to the equations governing how things reflect light

— Summary of Why Frustum Culling Matters, and Why It's Not Important by nothings on Github
Memory
Any IC that stores data for immediate use, often meaning addressable semiconductor memory, i.e. ICs consisting of silicon-based MOSFETs. Semiconductor memory is organized into memory cells.

Memory cell
An IC that stores a bit, and keeps its value until it is set or reset. The memory cell is the building block of any computer memory.

Storage devices can be categorized in three ways:
1. Random versus sequential, based on access
2. Volatile versus non-volatile, based on volatility
3. Primary versus secondary, based on usage
Random access versus sequential access
The processor can access a part of the memory either directly (randomly), allowing data to be read or written in approximately the same amount of time irrespective of its physical location;

or sequentially, where the time required to read or write varies significantly, due to mechanical limitations, depending on the physical location of the data on the medium.

RAM:
• DRAM
• SRAM

SAM:
• Magnetic memory devices, e.g. hard disk drives
• Optical discs

While SAM is read in sequence, arbitrary locations can still be accessed by "seeking" to the requested location. This operation, however, is often relatively inefficient.
Volatile versus non-volatile
Volatility means the memory requires power to maintain its data.

Volatile:
• DRAM
• SRAM

Non-volatile:
• Any kind of ROM
• Flash memory
• Magnetic memory devices, e.g. hard disk drives
• Optical discs
Primary versus secondary
Due to their higher density at lower cost compared to RAM, as well as resistance to wear and non-volatility, SAM are more suitable for secondary data storage.

Primary:
• DRAM for main memory
• SRAM for processor cache

Secondary:
• Magnetic SAM (e.g. hard disk drives and solid-state drives)
• Optical discs
DRAM versus SRAM
Their differences arise from the differences in their cell design:
• Dynamic RAM cell: one transistor and one capacitor
• Static RAM cell: one flip-flops (4 or 6 transistors)

DRAM cells have a capacitor, charging and discharging which can store a "1" or a "0" in the cell. However the charge in this capacitor slowly leaks away.

Power consumption:
DRAM cells slowly lose their data ⇒ they need to be regularly refreshed ⇒ DRAM requires a refresh circuit ⇒ DRAM has a more complicated circuitry than SRAM ⇒ SRAM is faster than DRAM ⇒ SRAM uses more power than DRAM when it is working

DRAM needs to be regularly refreshed ⇒ DRAM uses much more power than SRAM when it is idle

DRAM has more complicated circuitry than SRAM ⇒ DRAM is more complicated for interfacing and control and has more complicated timing requirements

Usage:
SRAM is faster than DRAM ⇒ SRAM is used where speed is more important than cost and size, such as the cache memory in a processor

DRAM cells are smaller ⇒ DRAM has more areal density ⇒ DRAM is cheaper per bit ⇒ DRAM is used for data or program code that a processor needs, commonly known as simply "RAM"
Lust for premature optimization kills productivity.
🍎🍌
Work hard to be lazy.
Kill your darlings.
Sound chip
- is an IC (chip) designed to produce sound through either digital, analog or a combination of both circuitries. Sound chips have oscillators, envelope controllers, samplers, filters and amplifiers. They also have signal generators as their fundamental modules which produce basic geometrical waveforms with variable timbre and pitch.

During the late 20th century, sound chips were widely used in arcade game system boards, video game consoles, home computers, and PC sound cards.

Programmable sound generator (PSG)
- is a sound chip that mixes a few (usually two or three) basic waveforms (pulse, square, triangle, sawtooth, etc.) and one pseudo-random-noise generator into a complex waveform, then shapes its amplitude envelope using attack, decay, sustain, and release time periods, so that the resulting waveform mimics a certain kind of sound.

Chiptune
- also known as chip music or 8-bit music, is a style of synthesized electronic music made using the PSG, or other music which intentionally sounds similar to it. While it has been a mostly underground genre, chiptune has had periods of moderate popularity in the 1980s and 21st century, and has influenced the development of EDM.
Creating Chiptune

“If you've ever listened to an 8-bit cover of a song, you'll know how evocative it is of some nebulous childhood memories. ... [Chiptune] is a wonderful way to inject life into songs regardless of genre. It's not really clear why these sounds are so pleasing to some of us, but there are certainly plenty of good uses for transforming a familiar song with 8-bit sounds.”

⚠️ reducing a track's quality to 8 bits ≠ achieving signature chiptune sound

An 8-bit sound file has a more discrete wavelength than a higher bit version of the same file meaning there's less information about the sound, resulting in a lower quality sound but not altering its timbre. Recreating PSG-generated chiptune sound is more complicated than just reformatting a file in 8 bits.

Converting audio to MIDI
• Find a MIDI version of your audio
https://www.bearaudiotool.com/mp3-to-midi
https://www.conversion-tool.com/audiotomidi
http://www.intelliscore.net/download.html

⚠️ The best option is the first one because when converting audio to MIDI, the quality of the resulting MIDI file highly depends on the structure of the input music, and will probably end up being nothing like the source track.

Converting MIDI to Chiptune
Download and launch GXSCC. It emulates a Famicom (NES) or SCC sound chip to play MIDIs like chiptunes.

For now ignore the complex GUI, and drag and drop your MIDI into the app window. Click the "Authoring" button at the top of the window. This will convert your MIDI to WAV and save in the same directory as the original.

To convert your WAV back into MP3 or any other format, use Audacity.

— Summary of How To Convert MP3 to 8-Bit by Arch
The desires of an implementer: to achieve a reasonable compromise whilst minimizing time and memory complexity, yet maintaining memory hygiene, hinder those of a designer: to imagine wildly and free of limitations and worrying of performance.

As a good programmer, you should try to somehow keep both sides alive.
Birth of C

Mid-1960s: Bell Labs, MIT and General Electric were jointly developing an experimental time-sharing OS called Multics which was written in #PL_I and assembly language.

Late-1960s: Though Multics featured many innovations, it also presented severe problems, which frustrated researchers at Bell Labs until they gradually withdrew from the project.

1969: A team led by Ken Thompson and Dennis Ritchie, who were among the last to leave, decided to re-implement their experiences in a new, smaller project. They implemented a hierarchical file system, the concept of processes and device files, a command-line interpreter, and some small utility programs, modeled on the corresponding features in Multics, but simplified. The resulting system was much smaller and simpler than Multics.

August 1969: “Ken Thompson's wife took their son on a trip to California. As a temporary bachelor, Ken had time to work. [He told me] 'I allocated a week each to the operating system, the shell, the editor and the assembler … during the month she was gone, it was totally rewritten in a form that looked like an operating system'” – Peter Salus

Thompson needed a language to make utilities for Unix. At first, he tried #Fortran, but soon gave up and made a new language: #B, a simplified #BCPL.

1970: Multics was short for Multiplexed Information and Computer Services. Because the new unnamed OS was a single-tasking one, Brian Kernighan coined Uniplexed Information and Computing Service which spelled Unics, and was later spelled "Unix".

1972: Ritchie started to improve B, which was too slow and could not take full advantage of specific hardware, and ended up creating a new language, #C, which was then used to make utilities running on Unix.

1973: The Unix kernel, which was originally written in assembly language, was then re-implemented in C. By this time, C had acquired powerful features, such as struct types.

1977: Ritchie and Stephen C. Johnson made further changes to the language to facilitate portability of Unix. Johnson's Portable C Compiler served as the basis for several implementations of C on new platforms.