{"id":3373,"date":"2011-05-29T22:30:49","date_gmt":"2011-05-30T05:30:49","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/?p=3373"},"modified":"2011-05-29T22:30:49","modified_gmt":"2011-05-30T05:30:49","slug":"nosefart-and-gme","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/nosefart-and-gme\/","title":{"rendered":"Revisiting Nosefart and Discovering GME"},"content":{"rendered":"<p>I found the following screenshot buried deep in an old directory structure of mine:<\/p>\n<p><center><br \/>\n<img loading=\"lazy\" decoding=\"async\" src=\"http:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/05\/knosefart.png\" alt=\"\" title=\"Knosefart -- proposed KDE frontend to the Nosefart player\" width=\"308\" height=\"253\" class=\"aligncenter size-full wp-image-3375\" srcset=\"https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/05\/knosefart.png 308w, https:\/\/multimedia.cx\/eggs\/wp-content\/uploads\/2011\/05\/knosefart-300x246.png 300w\" sizes=\"auto, (max-width: 308px) 100vw, 308px\" \/><br \/>\n<\/center><\/p>\n<p>I tried to recall how this screenshot came to exist. Had I actually created a functional KDE frontend to Nosefart yet neglected to release it? I think it&#8217;s more likely that I used some designer tool (possibly <a href=\"http:\/\/kdevelop.org\/\">KDevelop<\/a>) to prototype a frontend. This would have been sometime in 2000.<\/p>\n<p>However, this screenshot prompted me to revisit Nosefart.<\/p>\n<p><strong>Nosefart Background<\/strong><br \/>\n<a href=\"http:\/\/nosefart.sourceforge.net\/\">Nosefart is a program<\/a> that can play <a href=\"http:\/\/en.wikipedia.org\/wiki\/NES_Sound_Format\">Nintendo Sound Format (NSF) files<\/a>. NSF files are files containing components that were surgically separated from Nintendo Entertainment System (NES) ROM dumps. These components contain the music playback engines for various games. An NSF player is a stripped down emulation system that can simulate the NES6502 CPU along with the custom hardware (2 square waves, 1 triangle wave, 1 noise generator, and 1 limited digital channel).<\/p>\n<p>Nosefart was written by <a href=\"http:\/\/baisoku.org\/\">Matt Conte<\/a> and eventually imported into <a href=\"http:\/\/nosefart.sourceforge.net\/\">a Sourceforge project<\/a>, though it has not seen any development since then. The distribution contains standalone command line players for Linux and DOS, a GTK frontend for the Linux command line version, and plugins for Winamp, XMMS, and CL-Amp.<\/p>\n<p>The Sourceforge project page notes that Nosefart is also part of XBMC. Let the record show that Nosefart is also incorporated into <a href=\"http:\/\/www.xine-project.org\/\">xine<\/a> (I did that in 2002, I think).<\/p>\n<p><strong>Upgrading the API<\/strong><br \/>\nWhen I tried running the command line version of Nosefart under Linux, I hit hard against the legacy audio API: OSS. Remember that?<\/p>\n<p>In fairly short order, I was able to upgrade the CL program to use PulseAudio. The  program is not especially sophisticated. It&#8217;s a single-threaded affair which checks for a keypress, processes an audio frame, and sends the frame out to the OSS file interface. All that was needed was to rewrite open_hardware() and close_hardware() for PA and then replace the write statement in play(). The only quirk that stood out is that including &lt;pulse\/pulseaudio.h&gt; is insufficient for programming PA&#8217;s simple API. &lt;pulse\/simple.h&gt; must be included separately.<\/p>\n<p>For extra credit, I adapted the program to ALSA. The program uses the most simplistic audio output API possible &#8212; just keep filling a buffer and sending it out to the DAC.<\/p>\n<p><strong>Discovering GME<\/strong><br \/>\nI&#8217;m not sure what to do with the the program now since, during my research to attempt to bring Nosefart up to date, I became aware of a software library named <a href=\"http:\/\/www.fly.net\/~ant\/libs\/audio.html\">Game Music Emu, or GME<\/a>. It&#8217;s a pure C++ library that can essentially play any classic video game format you can possible name. Wow. A lot can happen in 10 years when you&#8217;re not paying attention.<\/p>\n<p>It&#8217;s such a well-written library that I didn&#8217;t need any tutorial or documentation to come up to speed. Just a quick read of the main gme.h header library enabled me in short order to whip up a quick C program that could play NSF and SPC files. Path of least resistance: Client program asks library to open a hardcoded file, synthesize 10 seconds of audio, and dump it into a file; ask the FLAC command line program to transcode raw data to .flac file; use ffplay to verify the results.<\/p>\n<p>I might develop some other uses for this library.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Methods for playing old video game music<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[29],"tags":[],"class_list":["post-3373","post","type-post","status-publish","format-standard","hentry","category-game-hacking"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3373","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=3373"}],"version-history":[{"count":6,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3373\/revisions"}],"predecessor-version":[{"id":3380,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/3373\/revisions\/3380"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=3373"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=3373"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=3373"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}