A quite old project of mine was sound synthesis. I know could be rather boring now, since there are many commercial and non-commercial apps in this topic.
I'd like to share my project hoping that some of my fellow masm coders would find something worthy and interesting.
Other goal is to get some test results and maybe some optimization ideas.
In my design the basic element is a module capable of generating or processing samples. These modules are arranged in a network, the network outputs the sound. Adding new modules is easy, thus adding new features is done quickly.
Modules created so far: constant, arithmetic operators, oscillators (different waveforms), an AHDSR envelope generator, LP/HP resonant filter, sequencer, clipper and delayer.
First goal is good sound quality, second is compactness. The synth code is supposed to be attached to 4k intros (could be too optimistic).
I would share the app for now. Source and description later if some find this interesting.
I hope I'll be able to update/recreate the sound synth web page.
EDIT 2009.06.23: scroll down for a newer version!
Greets
Gábor
[attachment deleted by admin]
what? no source?
Indeed, such code would be great to see. Pretty good sound and capability for the size also.
Lol, you could call it "GS" for "Gábor Sound" or "Gábor Synth." :bg
Nice :bg
sounds cool !!!
Sound synthesis is a great thing to do.
At this moment I'm learning how FIR and IIR filters work to use a fast but good LowPass filter in my FM broadcast proggy.
So, I would like to see your code.........
Greetz Siekmanski
Hi guys!
First of all, thanks for your posts. I'm glad that others find sound synth interesting.
Unfortunatly I don't have much time in these days, and the code needs some seriuos cleaning. There are some comments, but they are in hungarian. I guess that wouldn't be of much use for the most of you.
I hope to have some free hours to do this work soon. Have some patience :bg
Greets
Gábor
Seems to be just a proc lauching a wav file,i recognize the sound picked up on a site No ?
nah - we all speak fluent Hungarian here at MASM32 :red
Hi!
Quote from: ToutEnMasm on June 11, 2009, 07:58:17 PM
Seems to be just a proc lauching a wav file,i recognize the sound picked up on a site No ?
If you are trying to state that my app is a fraud only then I have to object! Since I'm quite an old member on masmforum, put shared some projects (no novice-level projects), I find the thought a bit insulting. :(
You should have simply debuged the exe. Besides show me a method that squeezes an about 30 sec sample into 8k...
Tomorrow I'll be playing football in a championship all day long, so either tonight or on sunday I'll create a package of the project that I can share.
I assure you and all now, that all code was written by me.
Greets
Gábor
i think he just wanted to know about where the song came from - not the code - lol
Gabor has been around here longer than many of us. :bg
Yes, even with "chip" samples, it would be difficult to squeeze that much sound (let alone the filter effects) into 8kb.
Perhaps, others can create new generators and effects for this platform, that would be impressive.
Good luck on your game tomorrow. :wink
(http://upload.wikimedia.org/wikipedia/commons/thumb/2/22/N%C3%A9meth_G%C3%A1bor.jpg/361px-N%C3%A9meth_G%C3%A1bor.jpg)
http://commons.wikimedia.org/wiki/File:N%C3%A9meth_G%C3%A1bor.jpg
I am curious to view how the sound is product,that all.
Quote
Tomorrow I'll be playing football in a championship all day long, so either tonight or on sunday I'll create a package of the project that I can share.
I wait for that
Hi folks!
First of all, thanks for your patience!
Actually I promised sharing my source on sunday, but I didn't specified which sunday :toothy
I hope the zip package contains all necessary files and the project can be compiled properly.
A few words about the project:
- There is a library and a testbed app.
- The important stuff is in the lib. The app creates a network and runs it. The network's components are described in the .net.inc files.
- The way the networks are described is very uncomfortable, actually it is hard coded in the source. (An editor or at least scripting support would be nice to have.)
- Though I added the subnet prototyping and instantiating feature (this was the reason of the delay), the network description can still hold duplicated information.
- The tesbed's source is a huge mess, it is full of dead code (in comments). The source doesn't have many usable comments, the few there is is in hungarian. ::)
I'm working on the weak points and further improvements. Hopefully I'll create a far more usable system soon.
I'm also working on the demo song. It is a very old chiptune by me written in Fasttracker.
The testbed app uses Ultrano's EasySound library for sound output. Greets and thanks go out to him :)
The RTF doc is short and brief, contains the basics only, but that's probably enough for a first overview.
I welcome every comments and opinions!
Greets,
Gábor
[attachment deleted by admin]
Ah, yes. It is not me in the picture. I'm no professional socker player. The championship was organized by the company I'm working for. We won :)
:U
:U :U :U
I haven't had much time to tinker with this yet, but it looks promising (and quite complex.) :U
Until then I am curious, the "song" is actually what---synth1.net.inc? That will take some studying, it is not obvious at first glance how it works. (Such is probably the hallmark of excellent code utilization.) :bg
P.S. Works great on XP x64 (where Beep is not implemented and fails silently.) Apparently this makes DirectSound the only way a user-mode-app can make any "sound" in this OS, which is a great niche role for this synth.
P.S.S. Here are a few links to check out.
http://joost.zeekat.nl/bassline.html
Here KB explains how he made the V2 singing synth used in many of the Farbrausch demos.
http://www.kebby.org/articles.html
Hi gabor
First of all, thanks for sharing your work! :wink
Looking through the code i found in the common.inc file a potential bug that may be very hard to trace down.
You are using an unsave memory location to store a temporary value onto the stack. All is fine until the OS decides to perform a task switch in between the intructions you are using. In this case, the temp value will be trashed. To avoid this, decrement the stack value by 4 before you save your temp value and finally restore the original esp value.
Some macros are coded the same way, like fldc, fildc, etc.
Regards,
Biterider
Thanks Gabor, for this nice example.
Hi guys!
Thanks for the comments!
Mark!
Yes, it is more complicated than it should be. This is the price of flexibility. Most of the soft synths use a very simple scheme: add some synths, drums, effects to the final mix, done.
I went a very different way: create synths, drums, etc, and add them to the final mix. The synth1.net.inc describes a synth only, main.net.inc is the main part. The song is stored there (in the bottom lines).
Since the last upload I created drums (a TR808 kick and a snare, I have a lot of trouble with hihats...) Thanks for the links!
Bitrider!
You mean the mov [esp-4],value trick? I think the stack is quite a safe place to store values. A task switch must not change the stack nor the registers. Or am I wrong? If it is preserved along the registers, the temp value stored there is safe. I haven't experienced crash or any other problems so far. Anyway, thanks for you remark!
I'll upload a newer version after I add polyphony.
Greets,
Gábor
anything below esp is "garbage"
or, at least, that is how things were in the old world - lol
it's simple enough to reserve the value
QuoteYou are using an unsave memory location to store a temporary value onto the stack. All is fine until the OS decides to perform a task switch in between the intructions you are using. In this case, the temp value will be trashed.
i've not looked at this code but are you refering to something like what I always do using the FPU like:
fistp dword ptr[esp-4]
mov eax,[esp-4]
which I use when I want to get a value into a register from the fpu when I don't want to set up a stack frame for optimization sake?
i've always done this and I thought that each task is assigned it's own stack.
i'm not being facetious, I really need to know if my above code could cause problems if a task switch occured between the two instruction.
with win32 code, i can't see anything wrong with it - lol
but, i think i might be inclined to preceed the operation with sub esp,4
in this case, it may be a byte or 2 smaller, in fact
sub esp,4
fistp dword ptr[esp]
pop eax
i use similar code when an API function wants an address to return a value,
especially if i do not care what that returned value is (like a write count or something)
or if i only want to return the value in reg instead of memory
this is ok if it is the last parm of the invoke (first pushed), otherwise, you should use ebp or possibly adjust esp accordingly
sub esp,8
INVOKE QueryPerformanceCounter,esp
pop eax
pop edx
Hi
all values below esp are UNSAVE. In case an interrupt is triggered in between the 2 transfer instructions, the OS may use the current stack for its own purposes. It has to keep all values >= esp untouched, but all < esp can be changed. It is only a matter of time that an app that uses such code snippets acts unexpected. Let it run for some days on control the results... I would never relay on such software for a nuclear plant controller :bg
Biterider
yes. your code makes sense.
actually if you pushed any register on the first line you'd save another 4 bytes.
push eax
fistp dword ptr[eax]
pop eax
and maybe prevent a stall on dependancy.
Thanks debndave. :U
EDIT:
the code should of read:
push eax
fistp dword ptr[esp]
pop eax
well - sub esp,4 is faster than a push - either way
yes it's just a shame that there isn't a increment/decrement instruction that deals with words and dwords like
incw eax ;increments eax by 2
decw ebx ;increments ebx by 2
incd ecx ; increments esp by 4
decd edx; decrements esp by 4
i've always found it strange that when intel made this instruction that they never considered that to increment a register to the next word or dword in a 1 byte opcode would be very useful ::)
lol - i was thinking the same thing - dang intel
of course, you can only have so many single-byte instructions
a 2-byte would be nice
EDIT
what would have been really cool would to have a few "programmable" instructions
so the programmer could set up a short sequence and use a 2 or 3 byte opcode to make it happen
of course, the cpu microcode would have to optimize it for us - lol - i am dreaming, i guess
better yet...
lea esp,[esp-256] ;reserve 256 bytes
.
.
.
lea esp,[esp+256] ;free reserved space
or...
lea esp,[esp-4]
fistp dword ptr [esp]
pop eax
Quote from: dedndave on July 02, 2009, 11:40:27 AM
better yet...
lea esp,[esp-256] ;reserve 256 bytes
Dave,
You are wasting precious resources - I am very worried ::)
lea esp, [esp-256] ; 8 bytes
sub esp, 256 ; 6 bytes
sub esp, 128 ; 6 bytes
lea esp, [esp-128] ; 4 bytes
add esp, -128 ; 3 bytes
lol Jochen - good afternoon (i think that's right)
i am surprised to see you count bytes instead of clock ticks
which is fastest ?
Quote from: dedndave on July 02, 2009, 12:43:19 PM
lol Jochen - good afternoon (i think that's right)
i am surprised to see you count bytes instead of clock ticks
which is fastest ?
In case of doubt, the shorter one - less cache pollution. In any case, there is not much to gain from removing the frame, as mov [esp+X] needs one byte more than mov [ebp+X] - see below...
004010A0 /$ 55 push ebp
004010A1 |. 8BEC mov ebp, esp
004010A3 |. 83C4 F4 add esp, -0C
004010A6 |. C745 F8 02000000 mov dword ptr [ebp-8], 2
004010AD |. C745 F4 03000000 mov dword ptr [ebp-C], 3
004010B4 |. 90 nop
004010B5 |. 83C4 80 add esp, -80
004010B8 |. 8BC4 mov eax, esp
004010BA |. 90 nop
004010BB |. C740 04 01000000 mov dword ptr [eax+4], 1
004010C2 |. C740 08 01000000 mov dword ptr [eax+8], 1
004010C9 |. 90 nop
004010CA |. C74424 04 01000000 mov dword ptr [esp+4], 1
004010D2 |. C74424 08 01000000 mov dword ptr [esp+8], 1
004010DA |. 83EC 80 sub esp, -80
004010DD |. C9 leave
004010DE \. C3 retn
MyProc proc
LOCAL v1, v2, v3
mov v2, 2
mov v3, 3
nop
add esp, -128
mov eax, esp
nop
mov dword ptr [eax+4], 1
mov dword ptr [eax+8], 1
nop
mov dword ptr [esp+4], 1
mov dword ptr [esp+8], 1
sub esp, -128
ret
MyProc endp
ok - now you have confused me again
i was all nice and level until i tried to read and understand that post - lol
is it me or are you hitting the vino ?
remember, it's 6 AM, here - i am only on my 2nd cup of coffee
I thought it was simple, but 6 AM is indeed very early :bg
In short: removing the stack frame is fine if you don't need local variables, but replacing it with a hand-made substitute
add esp, -80
mov [esp], SomeWeirdFigure
sub esp, -80
is simply a bad option. The stack frame itself costs 7 bytes, the substitute costs at least 6 bytes, plus one byte more for every usage because [esp] is a byte longer than [ebp].
Now theoretically we could embark on some timings... :bg
it isn't any worse than letting masm make the frame - lol
(no ebp register involved)
these guys were talking about using stack space as temporary storage
the alternative is some kind of Alloc/Free function
adjusting the esp register seems the simplest way
Quote from: dedndave on July 02, 2009, 03:45:21 PM
it isn't any worse than letting masm make the frame - lol
(no ebp register involved)
Sure a frame blocks ebp, but if you want to use ebp in a non-frame function, you need additional code anyway.
Hi!
Please test the last version. I heard it had problems under Vista...
Thanks and greets!
Gábor
XP SP3 ... OK
Biterider
seems to work fine here, Gabor (small, too :U )
XP MCE SP2
snappy tune ! - lol :boohoo:
works fine on XP SP2
Quote from: gabor on September 13, 2009, 05:43:28 PM
Hi!
Please test the last version. I heard it had problems under Vista...
Thanks and greets!
Gábor
Catchy...ye, you need to run as administrator under Vista. Must be a permission error of some sort.
Gabor,
if you figure out which API function requires elevated permissions, I'd like to know which one it is - lol
i try to write code that works under vista without uac problems, as well
thanks
Thanks for your help!
I cannot think of any parts of the code except the sound play component.
There are the following API calls:
- GetTickCount
- Sleep
- LoadLibrary
- GetProcAddress
- GetDesktopWindow
- GetProcessHeap
- HeapAlloc
- HeapFree
- CreateThread
- FreeLibrary
None of these seems suspicious to me. In general, I'd need a list of API changes between XP and Vista, and maybe Win7...
I'll try to find an explanation.
Greets
Gábor
wellllllll
the only one i see that might be a prob is CreateThread - that should be allowed
hmmmmmmmmmm
it would be much easier for someone running vista to troubleshoot it
Quote from: gabor on September 14, 2009, 02:46:29 PM
Thanks for your help!
I cannot think of any parts of the code except the sound play component.
There are the following API calls:
- GetTickCount
- Sleep
- LoadLibrary
- GetProcAddress
- GetDesktopWindow
- GetProcessHeap
- HeapAlloc
- HeapFree
- CreateThread
- FreeLibrary
None of these seems suspicious to me. In general, I'd need a list of API changes between XP and Vista, and maybe Win7...
I'll try to find an explanation.
Greets
Gábor
Well..the one you provided in ssn_m.zip (125.51 KB - downloaded 64 times.) runs fine without UAC. You must have changed something.
I tried debugging it and it breaks at 40120C with the error "Unhandled exception at 0x0040120c in testbed.exe: 0xC0000005: Access violation reading location 0x00000018."
0040119F ret
004011A0 ret
004011A1 push ebx
004011A2 push edi
004011A3 movzx ebx,word ptr [eax]
004011A6 inc eax
004011A7 cmp bl,0FFh
004011AA je 004011BB
004011AC inc eax
004011AD mov edi,ebx
004011AF and bh,0Fh
004011B2 shr edi,0Ch
004011B5 mov word ptr [edx+edi*4],bx
004011B9 jmp 004011A3
004011BB pop edi
004011BC pop ebx
004011BD ret
004011BE lea edx,[ecx+18h]
004011C1 call 004011A1
004011C6 ret
004011C7 pushad
004011C8 test byte ptr [ecx+0Dh],1
004011CC jne 004012A8
004011D2 or byte ptr [ecx+0Dh],1
004011D6 cmp byte ptr [ecx+0Ch],0
004011DA je 004011E6
004011DC cmp byte ptr [ecx+0Ch],1Ch
004011E0 jbe 004012A8
004011E6 mov ebx,7
004011EB push ecx
004011EC mov eax,dword ptr ds:[0040450Eh]
004011F1 cmp dword ptr [ecx+ebx*4+18h],eax
004011F5 je 00401283
004011FB movzx esi,byte ptr [ecx+ebx*4+18h]
00401200 movzx edi,byte ptr [ecx+ebx*4+19h]
00401205 mov ebp,dword ptr [ecx+8]
00401208 or esi,esi
0040120A jne 0040121B
0040120C movzx esi,byte ptr [ebp+edi*4+18h]
00401211 movzx edi,byte ptr [ebp+edi*4+19h]
00401216 mov ebp,dword ptr [ebp+8]
00401219 jmp 00401208
0040121B push ecx
0040121C mov ecx,ebp
0040121E mov eax,esi
00401220 call 00401418
00401225 mov ecx,eax
00401227 or eax,eax
00401229 jne 00401237
0040122B pop ecx
0040122C mov eax,dword ptr ds:[0040450Eh]
00401231 mov dword ptr [ecx+ebx*4+18h],eax
00401235 jmp 00401283
00401237 cmp byte ptr [ecx+0Ch],0
0040123B jne 0040125B
0040123D call 004011C7
00401242 mov edx,edi
00401244 movzx edi,byte ptr [ecx+edx*4+39h]
00401249 movzx eax,byte ptr [ecx+edx*4+38h]
0040124E call 00401418
00401253 or eax,eax
00401255 je 0040122B
00401257 mov ecx,eax
00401259 jmp 00401237
0040125B call 004011C7
00401260 pop edx
00401261 mov ebp,ecx
00401263 cmp byte ptr [edx+0Ch],0
00401267 je 00401283
00401269 or edx,edx
0040126B je 00401283
I've attatched a dump file...not sure if its of any use...let me know how I can help further=P.
Thanks elegem!
Since that version I've changed a lot. Only a total code review could help.
However the problem seems to be randomly appearing which tells me to look for unpreserved registers, incorrect use of stack or memory allocation issue.
Well, no doubt, I still have to work on this app...
Greets,
Gábor