ipatix / agbplay Goto Github PK
View Code? Open in Web Editor NEWMusic player for the most common GBA sound format
License: GNU Lesser General Public License v3.0
Music player for the most common GBA sound format
License: GNU Lesser General Public License v3.0
CGB instruments may be dropped in favor of other ones. Currently always the latest one played replaces any previous ones, but this is not accurate to original behavior. To correctly drop notes, track priorities and track numbers have to be considered and this issue is a TODO reminder.
Is it doable? I mostly want this for Golden Sun and The Lost Age, but I'm sure it could be useful in other games as well.
In GS2 especially there are a couple songs with "disabled" tracks, such as track 03 highlighted below (the most known case is one of the overworld themes missing a percussion track, this one is Lemuria)
I ripped them in GbaMusRiper and assigned the midis in question the correct instruments, in this case it's "Choir Aahs" (patch 52, like track 02 in the pic), and you can hear the result here.
Side note, for some reason GS2 has terrible sounding percussion, like it was pitched down or something, while GS1 is working fine. Maybe it's just me, but not sure why.
Edit: I re-checked and GS1 also has this problem.
Hey @ipatix!
I find it pretty hard to compile the project because of all the library dependencies, which partly themselves depend on other projects to compile.
Would you mind adding precompiled binaries of 'agbplay' to the "Releases" section?
That way Windows users like me don't have to go through the struggle/confusion of installing all these huge amounts of libraries.
Thanks in advance. :)
I would very much appreciate seamless infinite looping of a given track, given that the default (and only) behaviour is to play the looped part twice and fade out on the start of the third go-around…
On a related note, a button to loop a single track like what VLC has would be useful as well. Currently the only way to do that is to put it on its own playlist alone.
If a track is using the native Game Boy channel for its instrument, it would be neat if the tracker could show e.g. "Ch1", "Ch2" etc. somewhere. Would make it easier to identify them and also color them accordingly when making visualization videos.
When playing songs found in romhacks such as Touhou Puppet Play Enhanced Reloaded (which has a lot of custom music I'd like to record), some tracks skip mid-way through with the error:
FATAL ERROR on streaming thread: Nested track calls are not allowed: 0x C0A02A
You can replicate this by loading this romhack (version 6.8A is fine) and then playing the Ending Credits track loaded in the playlist.
Hi there - I was listening to The Legend of Zelda: The Minish Cap, song index 53 and noticed it's missing a shaker/bells sound at the beginning of the track.
Here's a recording of what the track should sound like (starts at 56:43) https://youtu.be/2euDSlH-_VY?si=a6qyxfFpRZmLRDoI&t=3403
The drums also sound very different, I'm unsure if that's an issue of say, a frequency cutoff or something else?
As far as I can tell, Sonic Advance 2 uses a completely standard m4a implementation, but I could be wrong about that. Anyway, you can hear the issue if you load up the game and play song 28 (True Area 53). There are two squares that are supposed to be panned to the left and right (pan 34 and 94), but they are both played completely center-panned. Additionally, AGBPlay shows them as being +30 and -30, even though it does not play them as such.
A very nice feature would be to have alias free waveform generation for the GB channels. This could probably increase the quality for GB heacy songs quite a bit. I personally don't know the math of the more complicated algorithms (at least for moment of writing this), so maybe someone knows a bit about that and could give me some hints ;)
Was surprised to find this program doesn’t provide any sort of command-line --help
.
Could you add this so people know how to address the binary and give it the things it needs? It looks like I’ll be poking at it until I figure out what works…
Just as a public todo:
GS2 Reverb: Current code is a "guessed" implementation and doesn't sound accurate.
GS1 Reverb: Tried to reimplement that by reading the assembly code. Doesn't seem to sound very good nor accurate.
Mario Golf: Assembly looks pretty similar to GS2 Reverb. Needs to be done some time too.
The attack of some notes on PSG ch 1 & 2 in the Ending Theme from Pokémon Ruby/Sapphire/Emerald (song 455 on all three ROMs) are completely missing.
Issue originated in 00f4fe5 and has persisted since.
See attached zip for examples of mGBA output and agbplay output.
example.zip
Since there are a couple of major things that I, and I believe also other, people would like to be implemented in agbplay I want to open this issue and collect things that I do plan to implement when I'm in the mood and I get some time again to work on agbplay.
agbplay's development was started in a time where I was getting a lot into the Linux world and applications. Thus agbplay has to some misfortune got the curses UI that we have today. While it does have the odd advantage on easily being usable remotely (which I have used before) I have to accept that this is really not a very useful trait. I know that there are some experiments with GUI support done here but I'd like to have the GUI somewhat be part of the main project.
This leads me to the plan of splitting the current program into 3 modules:
If you have any suggestions what the GUI and the headless version should be able to do, please let me know and I'll add it to a list. Also any ideas regarding the library interface would be welcome.
Currently settings have to be manually changed in the JSON. If you want to quickly change things that becomes rather cumbersome and I'd like this to be possible with the UI.
The current gsf support via the python script is somewhat hacky, as it merely creates a songlist. The original ROM is still required. Since from my understanding GSF strictly still is a ROM with everything but sound stripped, it should be possible to implement GSF support. This could vastly improve usability as people can just load one of the many tagged releases.
Perhaps this also depends on the game profile feature below since I don't want to implement GSF editing. Thus you'd have to choose between importing GSF tags or using an existing profile.
With ROM hacks people will often use the same game identification for ROMs with different playlists, different samples or different sound driver configurations. I want a quick way to select which profile the current ROM uses to change all the settings which are currently bound to the 4 digit game IDs. Perhaps even automatic detection of the profiles via magic bytes in a ROM which the modder can place somewhere.
Some people make enhanced versions of soundtracks and I'd come in handy to allow arbitrary instrument overrides to be defined. It should be flexible enough to for example allow a sample override for a specific song, Or like changing configuration values per song, per track, etc.
So called "high level emulation" for audio on GBA has been discussed for some time now. NanoBoyAdvance and mGBA have an option for it, but for most of the time (in my opinion) they don't sound very good nor do they work reliably. If libagbplay provides an API that resembles the complete feature set of mp2k/m4a it'd be cool to expose them such that emulator developers just have to hook the right funtions and forward them to agbplay while the emulator will then receive an audio stream.
Currently, agbplay will very almost always throw an exception if there is an error in the song data. The original code (of course) does not do this to avoid crashing the game. Unless a fatal error is occured, playback should continue with just a message in the debug log and the problematic sound being muted/skipped.
Currently agbplay really doesn't have versioning except commits on the master branch. For users it may become difficult to track if anything has changed. So there should be version in a vA.B.C type of scheme and a changelog which at least briefly mentions which things have changed (e.g. sound generation, enhanced reverb algorithm added, bug fixes, etc.)
I know that some people will not like this but at some point I'd like to replace the (flawed) Makefile with a more high level build system like CMake. Simply to make dependy management easier and allow easier inclusion by other projects via submodule.
This somewhat goes in hand with getting rid of the terminal curses UI. This is what currently prevents agbplay from working reliably across platforms due to differences in Unicode support. Ideally I want users to just be able to download the program and run it.
So if you have made it until here: Do you have any suggestion that is outside of what I've mentioned here? Feel free to discuss and leave your comments.
Did someone manage to compile agbplay on Mac OS ?
I installed the following dependancies with Homebrew : boost
, portaudio
, ncurses
, and libsndfile
.
When I tried to compile, I got the following error :
[Compiling] obj/CGBChannel.o
[Compiling] obj/CGBPatterns.o
[Compiling] obj/ConfigManager.o
[Compiling] obj/ConsoleGUI.o
src/ConsoleGUI.cpp:57:26: error: invalid operands to binary expression ('agbplay::Color' and 'int')
wattrset(winPtr, COLOR_PAIR(Color::WINDOW_FRAME) | A_REVERSE);
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/curses.h:1005:23: note: expanded from macro 'COLOR_PAIR'
#define COLOR_PAIR(n) NCURSES_BITS(n, 0)
^~~~~~~~~~~~~~~~~~
/usr/include/curses.h:879:42: note: expanded from macro 'NCURSES_BITS'
#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT))
~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:5278:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p);
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/string:3931:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os,
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/bitset:1091:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x);
^
src/ConsoleGUI.cpp:59:26: error: invalid operands to binary expression ('agbplay::Color' and 'int')
wattrset(winPtr, COLOR_PAIR(Color::DEF_DEF) | A_REVERSE);
^~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/curses.h:1005:23: note: expanded from macro 'COLOR_PAIR'
#define COLOR_PAIR(n) NCURSES_BITS(n, 0)
^~~~~~~~~~~~~~~~~~
/usr/include/curses.h:879:42: note: expanded from macro 'NCURSES_BITS'
#define NCURSES_BITS(mask,shift) ((mask) << ((shift) + NCURSES_ATTR_SHIFT))
~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/usr/include/c++/v1/memory:5278:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os, shared_ptr<_Yp> const& __p);
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/string:3931:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os,
^
/Library/Developer/CommandLineTools/usr/include/c++/v1/bitset:1091:1: note: candidate template ignored: could
not match 'basic_ostream<type-parameter-0-0, type-parameter-0-1>' against 'agbplay::Color'
operator<<(basic_ostream<_CharT, _Traits>& __os, const bitset<_Size>& __x);
^
2 errors generated.
make: *** [obj/ConsoleGUI.o] Error 1
I'm using Mac OS Sierra 10.13.5
i've compiled agbplay directly from github on my arch linux machine. it does run absolutely fine at first, but when i try running again, this message shown in the title appears on the white box at the bottom of the app.
when i hit the space key for playing the song, it just hangs on the first frame, and after that, any other input makes it freeze entirely, forcing me to kill it with ^c.
but not only that, i also get this on the console, it appears right when agbplay fires up, so i can only see it after closing agbplay:
https://pastebin.com/2vMj9Qap
it seems to be more related to alsa itself though, and i use pipewire. is it actually pipewire's fault? just a guess.
Pokemon mystery dungeon red rescue team dumping full files (not single ones) seems to emit some very long lengthy files.
Affected files:
026
027
028
029
030
031
034
035
037
117
118
119
122
127
They are ambient
and 214mb - 248mb
I have a clean Sonic Advance (Japan) (En,Ja) (Rev 1).gba
(No-Intro ROM naming) with md5sum 9e02f1c9f26f40905d43188b2bd2d98e
, which matches No-Intro. When trying to open it with agbplay, I get the following error:
Loading ROM...
Loaded ROM successfully
ROM verification: Bad Header Checksum: 2D - expected 2E
For the sake of interest, I edited the checksum to 2E
as agbplay wanted, and it happily opens the (now hacked, bad) ROM.
EDIT: Highly likely not related to the above, but subsong 0013 in Sonic Advance (with above ROM and hacked checksum 2E
) also sounds really off-key and unpleasant.
It would be neat if you could press "m" when over a track and have it muted. Would help with transcribing songs and figuring out the meanings of individual voices.
So I installed the latest version of Cygwin and compiled agbplay through that terminal. Everything was going smoothly until I tried playing a track from Lufia: The Ruins of Lore.
Whenever agbplay attempted to load a track, nothing is heard and the terminal would freeze a few seconds afterwards.
Tried again with Golden Sun 1 and the exact same thing happened.
I think I have a good hint towards what's causing this. Upon startup, the gray text box at the bottom of the terminal reads "No supported API found, falling back to: OSS". Apparently, OSS doesn't want to work with either Cygwin or agbplay, but I have no idea what APIs are -- let alone which ones are compatible with agbplay.
It might be a good idea to allow the size of the working reverb buffer to be set per-game in the .ini rather than hard-coding it to 0x630.
I haven't tested through alot of MOTHER 3's songs in this but I can't help but notice how broken "Battle With The Masked Man" sounds in this, namely the pitch bends with the sinewaves and other portions of the song do not sound correct at all.
I've supplied recordings to demonstrate and compare this behaviour, I'm not sure if these will show up in Github properly because they did something site-wide recently that made a good chunk of the website controls completely unresponsive...
Does this have anything to do with the mentioning of using sine waves rather than triangle waves for the modulators?
Hi there, thanks for the project! I'm looking to use agbplay in a non-interactive mode to just dump all the audio from a game: I have a hacked up thing to do it here: https://github.com/nbarena/bnrip/blob/main/agbdump/agbdump.cpp
Would you consider making this supported by agbplay by e.g. a command-line flag or a separate binary? Thanks!
I don't know if I did something wrong or if the rom is incompatible but here's this. Game is pac-man collection btw
/home/susiterry/agbplay/agbplay /home/susiterry/agbplay/rom.gba ✔
ALSA lib pcm_dsnoop.c:566:(snd_pcm_dsnoop_open) unable to open slave
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
ALSA lib pcm.c:2666:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_oss.c:397:(_snd_pcm_oss_open) Cannot open device /dev/dsp
ALSA lib pcm_a52.c:1001:(_snd_pcm_a52_open) a52 is only for playback
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib confmisc.c:160:(snd_config_get_card) Invalid field card
ALSA lib pcm_usb_stream.c:482:(_snd_pcm_usb_stream_open) Invalid card 'card'
ALSA lib pcm_dmix.c:999:(snd_pcm_dmix_open) unable to open slave
Cannot connect to server socket err = No such file or directory
Cannot connect to server request channel
jack server is not running or cannot be started
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
JackShmReadWritePtr::~JackShmReadWritePtr - Init not done for -1, skipping unlock
Loading ROM...
Loading Config...
Reading Songtable
Unable to find songtable
Just another todo. Sometimes when the terminal size is too narrow, agbplay will start to allocate ~4G memory and get really slow (especially if you don't have enough RAM!).
Not sure where it's caused. Theoretically too small terminal sizes should be clamped to a min size, but apparently doesn't work reliable.
The current ncurses 6.3 library on Arch, which is backwards compatible, allowed agbplay to build and link without errors. The only compiler warnings generated are unrelated, from double-to-float truncation.
I was able to play songs from some supported games (i.e. Kirby and the Amazing Mirror, Kirby Nightmare in Dream Land) correctly, with the visualizers and UI working as intended, and all the inputs listed in README appear to work. There is no unusual or concerning output.
The ncurses5-compat-libs
AUR package does not appear necessary to build nor run agbplay on Arch, so the official ncurses
package might be a safer recommendation. Can anyone verify? I have not seen this in any open or closed issues, so apologies in advance if it's something already known.
Gem Smashers uses m4a/mp2k, and saptapper detects the sound table correctly and outputs a playable gsf set.
Through agbplay however, it doesn't play any of the music/sfx, and skims over the songs, likely detecting them as empty.
What could the issue be?
Because I parsed for ints horribly, the reverb buffer gets set back to default if there are any letters in the hex number specified in the .ini file.
EDIT: This is now fixed in PR #26
Emitted files can't just be handed over to OpenAL unless using OpenAL-soft with float32 extension because they are stored as float32. I didn't see any option to store it as normal PCM.
It would be wonderful if player had a feature to export each channel of the song to a separate wav file without mixing. I would love to use this tool to make some oscilloscope videos, like this, for GBA music.
GSF rips contain parts of the ROM that is responsible for playing the music and sound, along with tags for each music track/sound effect contained in "MiniGSF" files. It would be nice to support those for easy track finding, fine-tuned track order, etc. without hardcoding everything into the INI file (given that the they are from games that use sappy engine).
agbplay
apparently always looks in the current working directory for its INI file, with no way for the user to command it otherwise. This makes it impossible to package for distros as I discovered: I put together an AUR PKGBUILD and this unfortunately halted my work.
My recommendation is to keep the current behaviour, but add a CLI option to specify it, and also make the program fall back to look in /usr/share/agbplay/
for the INI if it isn’t found in $PWD
. This would be perfect for my PKGBUILD.
Currently, games such as Super Mario Advance 2, 3, 4 and Sword of Mana cannot be loaded. This is the same for other GBA music tools, is it technically possible to output each track like other games?
I found a problem on track 0306 in Gyakuten Saiban 3 (ROM A3JJ
).
There is a neverending note on track 4 (around location 0x01436C7
).
You can compare this rip and a wav exported with agbplay (happens just after 00:45).
In the Neo Green Hill Zone Act 2 theme in Sonic Advance (track 0013 in soundlist), it seems that channel 4 has a problem. The instrument doesn't sound like it should. I don't know at the moment if this problem is present in other tracks.
The attached archive contains the first 10 seconds of the emulated version (correct) and of agbplay (the one with a problem) of the music involved.
NGZ2.zip
I'm trying to compile, but I get the following message:
[Compiling] obj/CGBChannel.o
make: g++: No such file or directory
make: *** [Makefile:48: obj/CGBChannel.o] Error 127
When I use O to pause playback and go to another song, it automatically plays. I am not sure if stop does the same thing. I got my use out of agbplay already. Keep up the good work.
In Chaos Angel Act 1 (song 44) in Sonic Advance 3, on actual hardware the square on track 10 has a low sustain value that continues playing for a bit, but in agbplay, the notes seem to decay to 0, giving them a very staccato sound; an example comparison can be found in this discord message. There also seem to be notes that get cut off or not played on hardware but do play in agbplay; not sure if this is related or not.
Please update README.md to include
Here's what the first notes should sound like: https://youtu.be/Jj8N8qg-wP8?si=VmOoCC6lBoLNbHha
The bagpipe drone at the beginning of the song seem to be down a minor 3rd when played via agbplay.
In cb7ddbd the rom was made a global. I have a particular use case, using this project as a library, which requires having multiple roms loaded and multiple sequences playing at once, would you accept a partial revert of this?
Would you also accept a PR which splits the project into two folders, core and gui?
I'm a bit confused and new to this when I install the zip master file I don't see the program for agb play in there could someone help me out or make a install tutorial setting this up.
I compiled a newer version of agbplay because I had an older version. It's great and all, but the .JSON playlists don't seem to be working. Even when I use roms that have the same rom code as in the .JSON file it doesn't seem to work. I don't know if I did something incorrectly on my end that made it so that this feature isn't working, but I thought I'd just let you know.
Btw, I'm on Windows 10, if that helps at all.
In Mother 1+2, there are 2 separate sound tables present in the ROM, one for each game. Currently agbplay only detects the first table (Mother 2) and ignores the second one (Mother 1). By patching the SongTable::locateSongTable()
to always return 0xf71c34
and it seems to play fine.
It also seems like that if I just let the original SongTable::locateSongTable()
to search everything until the end it will eventually find the second table as well. So maybe just change it to return an array and have the song list use 2 indices (i.e. table index and song index) to represent a song would fix this.
This might also work with other multicart titles (given that more of them exist).
Line 330 in dfdce57
So B24P
is the Europe version of pmd-red. I've been working on the pmd-red decomp which is USA (B24E
).
Is there any way to inherit one section to another? Currently, I just c/p the section under the header that agbplay created when I first ran it.
Not really a deal breaker. Just was curious, hah.
In some songs in FireRed LeafGreen, most notibaly the Trainer Battle theme (song 160), the pitch bends on the guitars will fail to pitch bend correctly compared against the MIDI being played on a soundfont.
On a normal load of the ROM, the pitch bends will end early and cause a blip of an extra note. It doesn't do this on shorter bends but for longer high pitched bends it's more noticeable.
Me and Kurausukun have found one workaround on modifying the MIDi file so the guitars are in seperate tracks.
It does not do this on the synth track that plays mostly the same notes or even track 4 on the guitars.
I tried this using a version of SAPPY 2006 and by setting the note limiter to 1, the bends played normally, no blips.
I can't play an audio from any rom because if I press O or spacebar it freezes the terminal. I also am unable to scroll and loop songs, change the sample rate or any settings. Me and a friend both tried this and we both have Windows 11 but nothing works. The only things we can do are Press A to add the song to the playlist and press E to export individual wavs to go into our files to listen to each wav to piece together the song. Is there something wrong with agbplay?
In CGBChannel.cpp, the following lines are inside CGBChannel::SetVol():
envPeak = clip<uint8_t>(0, uint8_t((note.velocity * vol) >> 10), 15);
envSustain = clip<uint8_t>(0, uint8_t((envPeak * env.sus + 15) >> 4), 15);
The second line should be:
envSustain = clip<uint8_t>(0, uint8_t((envPeak * env.sus + 16) >> 4), 15);
Assuming envPeak and env.sus were max value (0xF), this would not affect the upper limit. However, this fixes CGB instruments which have 0 sustain that are played at a low volume.
For example, Tiny Woods (song 125 in Pokemon Mystery Dungeon: Red Rescue Team) has a noise track which plays at volume 16. The noise itself has ADSR: {0, 5, 0, 0}. In agbplay, this track would play silently because of these two lines (envPeak would end up as 1, but envSustain would end up as 0), but in-game the track does produce sound. Changing the 15 to 16 in this line would fix this situation and set it to the correct level (envPeak 1, envSustain 1).
This is something I heard very rarely when using agbplay, but in a couple of songs in some games there would be this weird "warble" like distortion to some PCM tracks. One example is the VS mode theme (track 0000) in Minna no Soft Tetris Advance (right at the 1:08 mark). I also remember hearing it a couple of times in WarioWare Twisted too, I specifically remember the theme for the microgame "Dear John Letter" (track 0712) having heavy distortion, as well as Stumblebot (track 0788), yet a little more minor in the lead instrument . This issue was very rare but seemed important enough to be reported.
It seems agbplay is unable to automatically detect the songtable for Donkey Kong Country 3. Is there a way to manually specify an offset?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.