Jump to content

  • Log In with Google      Sign In   
  • Create Account


BGB

Member Since 02 Feb 2013
Offline Last Active Aug 31 2014 11:28 AM

#5157883 Memory allocator. Maintaining free list.

Posted by BGB on 03 June 2014 - 11:40 AM

Something else that may help is if you trade space for speed, and allocate pre-sized blocks of ints, say 32 or 64, and keep all blocks the same size.  If objects request a number of blocks of memory and they handle them internally it becomes a simple problem.  It would take more size of course because there'd be unused numbers, but its a thought.

 

(if I understand correctly) this is basically what I had meant by a slab allocator.

a slab allocator can be fast, but also reduce memory use by allowing multiple objects to share the same object-header (all of them will implicitly have the same logical-type and share other details).

 

for 4 byte items, you would allocate space for 256 items (1KiB), and then add them to a free-list of 4 byte items.

for 8 or 16 byte items, it would be similar, just allocating 2KiB or 4KiB instead.

 

then, for a range of items, you would use a number of free-lists of fixed-size members, say, using something like:

    nb=(sz+15)>>4;

to map the size to a specific free-list.

 

while this isn't perfect, allocations/frees can generally be made pretty fast (in the case where the free-lists aren't empty).

 

allocation in this case basically looks like:

    if(mm_freelist[nb])

    {

        ptr=mm_freelist[nb];

        mm_freelist[nb]=*(void **)ptr;

        return(ptr);

    }

    ... fall back to general-case allocation ...

 

 

faster is possible via a few tricks, namely having functions hard-coded for a specific allocation/free size, and using separate per-thread contexts (to avoid a need for locking during free-list allocations). for a general-case allocator, it is usually necessary to use a lock to prevent threads from stomping on each other (and for operations which work with or update the heap).

 

another trick here is to use pre-made "allocation handles", where one first creates a handle-object describing the type of allocation (size, type, flags, ...), and then does allocations/frees using this handle. internally, the handle may contain function-pointers for the specific allocation/free logic, and some data members that may be used for special free-lists or other things.

 

these may or may not use slabs, but will typically use a pool-allocation strategy (where dedicated free-lists exist for specific types of object, ...).

 

 

this may not necessarily apply to "general" code, but in my case code sometimes pops up which requires high-speed allocation/freeing of typically-small objects (often with specific type-information and special semantics/behaviors).

 

likewise, these large numbers of small objects comprise a big part of the heap (there are often millions of them in dumped memory-stats, 16-64 byte objects comprising the vast majority of these), vs the relatively small number of significantly-larger allocations (thousands of kB range objects, and tens of MB-range objects).

 

 

keeping the object-header small is generally also a goal.

 

currently, my MM/GC uses a 16-byte header, which basically holds:

    the object type-ID (objects in my main MM each have a qualified type, externally represented as a string giving a type-name);

    the object allocation size;

   data about where the allocation-call was made (useful for debugging);

   reference-counts (for ref-counted data);

   some flags and other things;

   a check-value (used to help detect if the header was corrupted, say by an overrun, *).

 

a lot of this is basically bit-packed, with a few special header sub-variants (such as for objects currently in the free-list, ...).

 

it was originally an 8-byte header, but was expanded to 16 partly as:

I wanted to support larger objects (the same header is used by large-objects as well, and would otherwise limit allocations in 64-bit apps to 256MB);

needed space for additional metadata;

many objects require 16-byte alignment anyways (for SSE/etc);

...

 

*: detecting corrupt headers is useful for things like heap forensics, where the MM may detect that a header is corrupt and try to dump diagnostic information and try to detect which memory object overflowed or underflowed, and try to make a guess as to where in the codebase to start looking for the offending code, in addition to raising an exception. also, we may free an object and it helps the MM to detect if a given object overran its bounds without requiring additional memory for additional check-values.

 

though, say, using 12-bits for a check-value, there is a 1/4096 chance for trashed-headers to escape notice, but this can be reduced some by use of additional "sanity checks" (example: does the size in the header fall within the range of what could fit within the given memory-cells and is appropriate for this part of the heap; is the object type-ID and source-ID valid?), but this needs to be balanced with performance (leaving it more as something for heap-analysis).




#5157527 Memory allocator. Maintaining free list.

Posted by BGB on 02 June 2014 - 07:24 AM

FWIW:

for allocating small objects (generally under 1-4kB), I prefer to use bitmaps over fixed-size cells instead of linked-lists.

 

pros (vs a linked-list allocator):

they tend to have a smaller per-object overhead (no internal pointers needed, but a constant per-space overhead for the bitmaps);

they will implicitly merge adjacent free memory once memory is freed;

object lookup from arbitrary pointers can be made very fast (good for things like dynamic type-checking and similar, which can be made O(1));

basic logic is fairly simple;

easier to add logic to detect/analyze overruns (they will corrupt object data, but will not necessarily cause critical damage to heap metadata, which may be stored elsewhere in memory).

 

cons:

direct allocation/freeing becomes linearly slower depending on object sizes (need to scan/update bitmaps);

high overheads for larger objects (due using lots of bitmap entries / cells);

more limited "effective range" of object sizes (vs being similarly effective over a wide range of sizes, as-is the case for lists).

 

partial solutions:

use a pool allocator to speed up allocation/freeing (the pool allocator then serves as the primary allocator, and uses the bitmap allocator for backing, where the pool-allocator has free-lists of fixed-size items);

use several different strategies, picking the one most appropriate for the given object size.

 

for example, in my current main allocator, it works sort of like this (16 byte cells):

* under 16 bytes: use a slab-based allocator (say, allocate memory for items in groups of 256 and pad them to a power-of-2 size);

* 16-6143 bytes: use bitmap allocator (with a pool allocator to make it faster);

* 6kB+: use a "large object" heap, which manages memory objects mostly via sorted arrays pointers and object headers (mostly using binary lookup and binary-insert).

 

I had at one point considered adding an additional layer of 256-byte cells which would be used for 4kB to 256kB, but had not done so.

 

 

though, yes, a linked list works. a few ideas:

pad object sizes up to multiples of a certain value (ex: 8 or 16 bytes), which will help reduce fragmentation;

use free-lists of fixed allocation sizes (avoids the need for searching), or size-ranges (reduces searching);

only merge with next item on free, and/or have a special case to walk the heap and merge adjacent heap items as-needed.




#5156148 lib hell

Posted by BGB on 26 May 2014 - 05:30 PM

Im not quite see it clearly (got not so much experience) and maybe some will help me to claryfy this picture
 
Im mostly talking about windows platform (though I may be courious if on other platforms things looks better)
 
As far as i know there is no standarisation of lib (static libraries format)
so there we got some static lib-hell (my own name for this) where given static lib may only works with some compiler say VS or say GCC and not across them all (as it should be) [I am speeking on one specyfic system
mostly win32 or win64]
 
1) is this true?

 
simple answer: yes.
 
 
less simple answer: there is some informal/de-facto standardization of LIB and OBJ file-formats, at least as far as Windows goes (as AR archives and COFF objects, known as OBJ/LIB with MSVC and O/A with GCC). however different compilers have various minor format differences (in terms of structures both within LIB/AR and the COFF objects), making things problematic.

some compilers had also used different formats entirely (for example, a few older compilers had used a 32-bit version of the OMF format and its associated LIB format instead of COFF/AR). there are also differences in the contents of various header-files (ex: what exactly is a "FILE"?), there are differences in terms of parts of the C ABI, and often a very different C++ name mangling scheme and ABI (so C++ object-files are usually incompatible).
 
the end result is that while sometimes it is possible to force things to link between compilers, usually the result will either not work (at all or at least not correctly) and/or be prone to crashing.
 
 

2) do this incompatibility occur between across verisons of compilers 
or it only occurs between different compilers (I mean can lib not works if 
made with older version of compiller with the newer version of the same 
brand compiler or in one compiler it will work for all verions)

it can apply between compiler versions for the same compiler as well.

for example, both MSVC and GCC have changed their ABIs in various ways between compiler versions, so code linked between different compiler versions is prone to not work and/or result in crashes.

this is generally less of an issue for DLLs, as the basic C calling conventions (cdecl and stdcall) are pretty much frozen, and also both MSVC and GCC agree in most areas WRT the basic C ABI, and MS is adverse to changing things which will break existing software.

however, the C++ ABI is compiler specific, and there are a lot of minor edge cases where the C ABI differs between compilers (namely WRT passing/returning structs, the handling of types like "long double" and "__m128", ...), so some care is still needed.

it may also be observed that many/most Windows libraries tend to use a fairly constrained C subset for their APIs (and COM and similar are built on top of the C ABI).

 

3) are the gcc/vs/intel/what else partially compatible - or in general mostly not compatible
4) is there a way of mending a incompatible lib in some way ?
 
tnx for the answer (it seem to me tah it may be hard to answer thiss fully but at least partially - i would like to build some wiev on this static lib - hell  in windows, how the things look like)

when possible, build things from source all with the same version of the same compiler.


#5149892 Alpha blending with a color that has no RGB components

Posted by BGB on 27 April 2014 - 11:12 AM

 

PNG is stupid in that it's authors made the assumption that the RGB values of transparent pixels aren't required.
If an artist tries to have pixels that have a particular colour value, but a zero alpha value, PNG jumps in and turns their colours into garbage.
AFAIK, the RGB values of invisible pixels in a PNG file are *undefined*, they're just garbage.

If you need this feature, which games very often do, then PNG isn't a suitable file format...
I personally deal with this problem by using a pair of two non-transparent files: one contains the RGB values, and the other contains the alpha values in the R channel... :-(

[edit] if you don't need artist-authored values, and are ok with just some constant colour, then you can do this yourself after loading the PNG and before passing the pixel data to GL. Just loop over each pixel, check if alpha is zero, and if so, set RGB to your constant.

 

For some time, I also blamed the .png file format for this problem, but apparently it's not a deficiency of .png, but a deficiency of Photoshop's png exporter.

 

 

yeah, there is nothing in PNG itself to actually cause such an issue.

 

basically, it just stores raw RGBA data with some predictive filtering and Deflate compression, which works the same regardless of whether or not the pixel is transparent.

 

it is then up to the exporting application to determine what to save in these pixels.

some programs will just save whatever would have been present in the pixel if the pixel were not transparent.

some others will simply just clamp transparent areas to black, or maybe flood-fill with some other color.

 

"garbage" could be one of several varieties depending on the exporter:

is could just stupidly leak uninitialized memory values, which would be bad (not good for compression, ...);

or, it could be the encoder being clever, and forcing all prediction deltas to 0 in an attempt to get better compression (this being most likely to cause sort of a smeared-banding or rainbow-like patterns in transparent areas).

 

 

I don't personally have any experience with Photoshop (mostly just with GIMP or Paint.NET), and don't really know what it does in this case.




#5141476 Does this type of collision phyisics have a name?

Posted by BGB on 23 March 2014 - 11:14 AM

As for drawbacks, the main problem is that a circle is not necessarily a close enough representation of your object. For a long thin object the bounding sphere will contain a huge amount of empty space. That will lead to a lot of false positives in intersection tests. An axis aligned or oriented box is a tighter fit in many cases.

Whether circles are good enough for your circumstances, well, that of course has more to do with your circumstances than the circles.

 

it also depends on whether or not you need to deal with objects which may have an arbitrary rotation.

with a circle or sphere, no matter how the object is rotated, it will fit within the existing space.

 

 

if you have to make an axis-aligned bounding box (AABB) over every possible rotation, generally it will involve more empty space than the sphere, though bounding box is generally more accurate if bounding a particular rotation.

 

though, for oriented bounding boxes (OBB), these are often a tighter fit, but collision checks are more expensive.

likewise for convex polyhedra (where the object is bounded by a collection of bounding planes, or the 2D equivalent being a polygon).

 

so, generally, if using a more expensive solid-type (like an OBB or polyhedra), it may still make sense to use sphere checks first to eliminate impossible collisions early.

 

likewise, they may have other uses, like a sphere traveling through space is simpler to bound accurately than an AABB, and may also have advantages for certain other cases, like when trying to find the initial collision point for fast-moving objects, ...




#5140816 divide on subsystems

Posted by BGB on 20 March 2014 - 06:56 PM

in my case, my engine is basically divided up somewhat...

 

renderer stuff:

    "lbxgl": high-level renderer, ex: scene/model/animation/materials/...

    "pdgl": low-level renderer, ex: texture loading, OS interfaces (WGL, GLX, ...), various utility stuff.

common:

    "btgecm": lots of stuff needed by both client and server, ex: voxel terrain, map loading, some file-format code, ...

    "bgbbtjpg": graphics library, deals with image loading/saving, video codecs / AVI / ..., compressed-texture formats, ...

    "bgbmid1": audio library, deals with mixing, MIDI, text-to-speech, several audio codecs, ...

client:

    "btgecl": deals with "client side stuff", mostly sending/recieving messages from server, updating the scene-graph, ...

server:

    "btgesv": server-side stuff (game logic, simple "Quake-like" physics, mobs / AI, ...).

    "libbsde": rigid-body physics simulation stuff, largely not used at present in favor of simpler physics.

script / infrastructure (back-end):

    "bgbgc": garbage collector

    "bgbdy": dynamic types, object-system stuff, VFS (virtual filesystem), ...

    "bgbsvm": script VM

    ...

 

generally I had split libraries up when it gets sufficiently big that it is either unwieldy or takes a long time to rebuild.

in the past, this had generally been somewhere around 50 kLOC.

 

this is not always the case, for example, my high-level renderer ("lbxgl") is ~ 111 kLOC and is not split up.

adding up a few renderer related libraries, works out to around 303 kLOC.

 

current project line-count: 879 kLOC.

 

granted, this project has kind of been ongoing for a while...




#5138634 LLVM Library for Scripting

Posted by BGB on 13 March 2014 - 02:43 AM

I tried to embed SpiderMonkey and V8 at first, but my attempts to build them for msvc weren't fruitifull so far, same for Mono.

Squirrelis quite handy, and has a really cool syntax.

 

my thoughts:

looked at LLVM before, but it looked a bit much like using a sledgehammer for a job better suited to a clawhammer (ex: typically stuff involved in running script code). what it provides isn't exactly a great fit for what makes sense for a typical script-language backend.

 

 

there is kind of a common mindset though of people using the biggest / most powerful / most "industrial strength" tool, regardless of whether or not it is most appropriate for the task. using something overly big and heavyweight though may actually make things worse in terms of development/maintenance work and sometimes also performance (say, if the workload of the task does not match the workload the tool was developed for).

 

 

SpiderMonkey and V8: dunno. usually GCC -> MSVC porting is doable, if sometimes annoying, though it requires a bit of a willingness to "dig in" and sometimes partly rewrite things, ... wouldn't think it would be as much of an issue for SpiderMonkey as IIRC Mozilla uses MSVC for their Windows builds, so the code should be reasonably free of GCC-isms. what little I had looked at them, things seemed "fairly reasonable" at least.

 

Mono: ... I have looked at the code for this before. at the time I found it almost absurdly questionable/bad even for performance-oriented VM back-end code (clear abstractions were largely absent, pretty much everything was tangled up in everything, ...). now, I am less certiain, as dealing some with performance-oriented code may have increased my tolerance for "general nastiness" to some extent (though even as such, I still prefer to try to maintain things like consistent internal API abstractions and uphold naming conventions and similar...).

 

not really looked too much into Squirrel personally.

 

 

in my case, I am using my own VM technology, and my efforts are pretty well invested in this. major/core pieces of codebase architecture and infrastructure are not something that can be easily swapped out without a lot of pain. more so when one considers that "little things" done by one things may not be done, or may be done a fair bit differently, with something else.

 

also partly because it has been developed incrementally in an on-off manner over the past 15 years or so, and 15 years ago, there weren't as many good options available for scripting, and at the time it seemed like such a simple task to throw together a naive interpreter.

 

maybe funny, or sad, or just some sort of personal fault, that things often start out so small/easy/simple, but often over a period of time seem to mutate into something a bit far from being nearly so small or simple anymore.




#5137939 How Do You Organize Your Thoughts ? Data Files ?

Posted by BGB on 10 March 2014 - 04:04 PM

in my case, things are organized recursively roughly by category, for example:

renderer

    world rendering

        lighting / shadows / ...

        rendering voxel terrain

    3d character models

    texture and shader / material management

    ...

game logic / server-side logic

    entities / AI

    physics

    world stuff

    player stuff

    ...

client-side / input-handling / UI

common

    world loading/management stuff

    voxel terrain stuff

    console related stuff (processing commands, cvars, ...)

stuff for image-processing and video data / codecs / ...

stuff for audio-processing (sound effects, mixing, ...)

assorted math stuff

    vector and matrix functions

    primitive types (AABB / OBB / ... collision-checking, ...)

    things like polygon clipping and similar (clip triangle by plane, ...).

infrastructure

    virtual file-system

    memory manager / GC

    dynamic type and object facilities

    script VM VM / interpreter

    ...

 

 

within this, things may be broken up into specific topics, for example, within image and video stuff, there might be files or groups of files dedicated to specific image formats or codecs, as well as specific data representations (stuff related to DXT5 or BC7, for example).

 

however, there may be some amount of overlap, for example, several formats may share things like the DCT / IDCT transforms, as well as a lot of special case-code, such as YCbCr 4:2:0 (or YCbCrA 4:2:0:4) to DXT5 or BC7 conversion logic.

 

but, this may be kept separate from the renderer, which may just be like "give me those video frames as BC7", and may not really care how the video-decoder stuff does so (or all the hair that goes into real-time BC7 transcoding, or its quality limitations, ...). likewise, the video-codec logic may not need to care about the specifics of how the texture-manager streams stuff to the GPU (PBOs vs glCompressedTexImage2D calls vs ...), its main goal just being to fill the buffers quickly. likewise, the video-codec may have some stuff otherwise irrelevant to the renderer, such as logic to allow it to be callable from VfW or DShow or plug into VLC, ...

 

 

beyond this, generally things are organized by similarity.

for example:

BCn stuff

    DXT5 stuff

        whatever -> DXT5 block-level conversion

            variants based on input format (RGBA, BGRA, YUV420, ...)

            variants based on secondary requirements

                slower but higher quality (such as for texture loading)

                faster but lower quality (such as for video playback)

        DXT5 -> whatever (have DXT5, need RGBA, BGRA, or YUV420 or YUV422, for example)

        image-level functions (convert a whole image, flip image, or convert+flip, ...)

        ...

    BC7 stuff

        like above, but all over again for BC7...

    BC6H stuff

        likewise, but for floating-point textures...

    ...

 

so, one might end up with a source file dedicated to various "whatever to DXT5" conversion functions, another for "whatever to BC7 mode 5", ...

 

elsewhere in the engine, it may be a different set of files dedicated to each specific enemy type (enemy-specific behaviors and animations, ...).

 

or, in an interpreter, files dedicated to various arithmetic operators or array load/store operations or field get/set operators, ... (because we might need versions of the operators specific to various operand types, ...).

 

a lot of this is not necessarily because anything is particularly difficult, but mostly because of performance constraints and special cases and variations, which may in turn sometimes result in a lot of hair and bulk.




#5135742 Double or more statements in one line, how does the debugger behave?

Posted by BGB on 01 March 2014 - 04:57 PM

n+=2; Func(n);
If two statements are typed in the same line, how does this affect the debugger? Since the debugger
picks line numbers apparently(in GDB and the Visual Stuido debugger)

 

 

in my experience with the VS debugger, if you have a single line (with multiple statements), it is treated as a single unit (for things like single-stepping, ...), but if spread over multiple lines, then each will executed individually.

 

this has the result that how things are formatted will effect how stepping works:

for(i=0; i<1000; i++)DoSomething();

vs:

for(i=0; i<1000; i++)

    DoSomething();

 

where the former will be stepped over all at once, but the latter will involve needing to step through each iteration of the loop.

 

an exception seems to be function calls, which IME seem to (normally) always behave as a single unit (although it is possible to step-into called functions and similar within argument lists).




#5135499 Logic (That's what programming is centered around right?)

Posted by BGB on 28 February 2014 - 04:51 PM

Learning to write algorithms would probably come from studying a lot of existing algorithms and software patterns. It about of being able to express a problem in a generic way, and knowing which pieces can go together for the bigger picture. It's also about being able to articulate how you go about solving a problem yourself.

A formal logic course won't teach you that.

 

yes. a fair bit of programming is mostly rehashing things which already exist, or taking something that have been used in one context and applying it in a slightly different context, ...

 

probably having an ability to fit largish amounts of random stuff into their memory is on-par with having an ability to really understand or reason about it.

and, with memory, one can also benefit that others people have largely done most of the actual thinking and reasoning work, so to a large degree it becomes more a matter of remembering having seen a good or at least adequate solution which can be made to fit the current problem (or maybe remembering various solutions and ranking them according to some or another metric, ...).




#5134598 Audio Programming

Posted by BGB on 25 February 2014 - 06:26 PM



Do you happen to know a good book about it? I ordered "audio programming book" and I already know a fair bit of DSP and audio stuff thanks to my degree. I think I will lack the math and some programming mostly.

Again this is not for a full career or for a degree, it's just to learn on the side.

 

 

I have little idea about books here.

 

I mostly just learned stuff by writing code, mostly using some amount of guesstimation and trial-and-error and similar, and in some cases trying to scavenge information off the internet.

but, yeah, as noted by another poster, relevant information is hard to find...

 

 

even then, one may still end up with issues, which need to be solved in slightly inelegant ways.

one example was recently noting while recording in-game video, that the audio and video were out of sync.

 

the video was frames as seen by the renderer, and the audio was whatever was coming out of the in-game mixer at that particular moment. however, the audio was slightly ahead of the video. the solution was basically to insert an audio delay into the video recording, then tuning the delay-values until they matched up. why? because it apparently takes a little bit of time between when audio is mixed in-game, and when it comes out of the speakers.

 

 

but, yeah, the major thing about audio I suspect is mostly about knowing basic programming stuff, and being generally familiar with working with arrays.

 

for example, your audio data will typically be in the form of arrays of "samples" at a particular "sample rate".

if you want to produce output samples, typically it will consist of a loop, which will calculate each sample and put it into the output-array.

 

typically, the input audio is also in the form of arrays of samples, so the position of the current sample being mixed may be used to calculate the position of the input samples you want to mix, ...

 

 

however, often the desired input sample doesn't land exactly on a sample, so then we interpolate. for example, a common strategy is linear interpolation, or "lerp" (invoking math here):

    lerp(a, b, t)=(1-t)*a+t*b

where a and b are the adjacent input samples, and t is the position between a and b.

 

another option is using a spline, for example, one possible spline function:

   splerp(a, b, c, d, t)=lerp(lerp(b, 2*b-a, t), lerp(2*c-d, c, t), t)

where a,b,c,d are the adjacent input samples, and the desired value is between b and c.

2*b-a and 2*c-d are what are known as linear extrapolation, where c'=2*b-a (c' being the value of c as predicted by extrapolating from a and b).

we effectively then form a pair of predictions, and then interpolate between these predictions to get an answer.

 

the idea here is basically that with a series of points, you might have a curve which passes through these points, and it may make sense to be able to answer a question "given these points, where will the value be, approximately?".

 

 

this works pretty well if the input and output sample rates are "similar", but if there are considerable sample rate differences (such as in a MIDI synth), then the audio quality may suffer (due to "aliasing" or similar).

 

one strategy that exists is to start with audio at a higher sample-rate (say, 48kHz or 44.1kHz), and then recursively downsample it by factors of 1/2 (say, by averaging pairs of samples), for example, we create versions of the audio at various sample rates:

44.1kHz, 22.05kHz, 11.025kHz, 5.513kHz, ...

 

then you can calculate approximately which target sample-rate you need, interpolating the sample position from adjacent sample-rates, and then interpolating between these rates to get the desired sample. (if familiar with the idea of mipmapping in graphics, this is very similar...).

 

most of this can be wrapped up in a function though, as normally you don't want to deal with all this stuff every time you want a sample.

example:

float patchSamplerInterpolate(patchSampler patch, double sampleBase, double targetRate);

 

where patchSampler here may represent a given piece of audio (a patch or waveform or whatever term is used for this).

 

 

other various thoughts:

consider picking some unit other than samples as your unit of time measure, for example, it may make some sense to do a lot of calculations in terms of seconds or similar (when dealing with lots of audio at different sample-rates or with a lot of scaling/... seconds may make more sense as a basic time-unit);

use double (and not float) for audio sample positions and time-based calculations (when it comes to sub-sample accuracy over time-frames of many minutes or more, float doesn't really hold up well);

it may be useful to consider what happens when time values are before the start or after the end of a given patch/waveform, for example, does it loop or is it followed by silence?, ... so, for example, the interpolation function might use a flag, which indicates whether the sound is discrete (non-looping) or continuous (looping), and then generate sane values for out-of-range sample positions.

 

potentially, various effects may be implemented in terms of functions, either using raw sample arrays, or by building on top of abstracted interpolation functions (there are tradeoffs here, raw arrays can be faster, but tend to be a little more hairy/nasty).

 

 

another tradeoff is, for example, whether to store audio data in terms of 16-bit shorts or similar, or use floats.

in my case, I tend to use 16-bit PCM (or sometimes compressed representations) for storing raw audio data (sound-effects, ...), but floating-point arrays for intermediate audio data (stuff currently being mixed, ...).

 

 

but, yeah, otherwise dunno...




#5134508 Audio Programming

Posted by BGB on 25 February 2014 - 01:44 PM

how to answer?...

 

in a basic sense, working with audio is mostly about loops, arrays of numbers, interpolation, and doing basic calculations on these numbers.

 

beyond this, and maybe dealing with issues like getting audio to/from the sound hardware, or dealing with specific audio file-formats, there doesn't really seem to be a whole lot particularly notable IME.

 

things are made simpler mostly in that computers are fast enough that one can generally get along pretty well using some fairly naive math and lots of floating point calculations (say, in contrast to real-time video processing, which is much more speed-critical).

 

 

dealing with more specific tasks, like writing a mixer for a 3D world, or writing a MIDI synthesizer, or doing text-to-speech, ... may involve a few more things specific to the use-case or situation, but these aren't really a whole lot fundamentally different from the above (it would be things like calculating how loud/quiet something should be based on distance, or how much to Doppler shift and delay it based on its current velocity and distance, or playing a sound clip for an instrument faster or slower depending on the note being played, ...).

 

trying to find information about various audio topics online may sometimes be made more difficult by lots of information being either in the form of opaque mathematical notation and/or depictions of various analog electronic devices, but this is a secondary issue I think.

 

 

in games though, a lot of people mostly side-step all this stuff by using audio-libraries though.




#5134483 Text-To-Speech libraries?

Posted by BGB on 25 February 2014 - 12:33 PM

sadly, there seem to be pretty few options here.

 

as noted above, there is MS-SAPI and Festival.

 

 

there is also FreeTTS, which is written in Java.

there are also several GPL TTS libraries.

 

as for using SAPI, it comes with a few drawbacks:

using it is not portable to non-Windows targets;

one is more or less at the mercy of the OS and what software the user has installed as to which voices are available.

 

 

in my case I wrote my own, but it mostly uses speech data originally scavenged from Festival (and converted into custom formats).

I have not had as much luck with various attempts at creating synthetic voices, and doing the extensive recording and similar needed to make new custom voices is problematic, ...

so, yeah, data is probably the harder part here.

 

to some extent, in my case, it is possible to post-process the audio to change pitch and a few other things (at the cost of a reduction in terms of audio quality and intelligibility), as well as cause generate speech emitted from various in-world entities, ...

 

it is not particularly good, but it basically works.




#5122208 Transparency problem in voxel terrain!

Posted by BGB on 08 January 2014 - 12:26 PM

not sure about the specifics of Unity 3D, but in general:

draw solid geometry first;

then draw transparent geometry in back-to-front order.

 

generally, yes, solid geometry and transparent geometry are kept separate.

 

 

in my engine, the chunks with transparent geometry are essentially sorted by their distance from the camera, then transparent geometry is drawn with the furthest chunks drawn first.

this seems to mostly work.

 

a few things are also drawn with depth-writes disabled, which also has sometimes "interesting" side-effects, but is needed to help reduce problems with intersecting geometry causing ugly self-clipping artifacts. if transparent geometry is drawn in-general this way, rather than out-of-order drawing resulting in things being not-drawn, it will result in blending issues. usually, the blending issues are slightly less ugly though.




#5120248 Math?

Posted by BGB on 31 December 2013 - 01:32 AM

lots of vector math, followed by working with scalar floating-point math, lots of integer math, some occasional fixed point math or other oddities, matrix operations, possibly quaternions in a few cases, ...

 

if you know basic Algebra type stuff, and can basically understand with vectors, that is probably most of it.

 

so, yeah, maybe "Algebra" + "Analytic Geometry".






PARTNERS