Re: Any appetite for patches for EMMS support for SNES SPC files?

Warren Wilkinson <[email protected]>
Newsgroups gmane.emacs.emms.user
Organization Personal Email
Message-ID <[email protected]>
> Yoni Rabkin <[email protected]> writes:
>
> Please write back when you get the OK from the copyright clerk.

Will do!

> mpv also uses `emms-player-base-format-list', but using it is
> optional. In any case, there is no problem with adding spc to that
> list.

I downloaded and tested mpv: mpv can also playback .spc files.

> As for the rest, can you please split it out to a separate file such as
> "emms-info-native-spc" or "emms-info-native-id666" or similar? That will
> scale better as we add more native info methods.

I've split it into emms-info-native-spc. I choose "-spc" over "-id666"
because that's probably easier for a person trying to find the relevant
code.
snes.patch (text/x-diff, 5.4 KB)
diff --git a/emms-info-native-spc.el b/emms-info-native-spc.el
new file mode 100644
index 0000000..ebfde2c
--- /dev/null
+++ b/emms-info-native-spc.el
@@ -0,0 +1,95 @@
+;;; emms-info-native-spc.el --- Native Emacs Lisp info method for EMMS -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2023-2024 Free Software Foundation, Inc.
+
+;; Author: Warren Wilkinson <[email protected]>
+
+;; This file is part of EMMS.
+
+;; EMMS is free software; you can redistribute it and/or modify it
+;; under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; EMMS is distributed in the hope that it will be useful, but WITHOUT
+;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+;; License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with EMMS; see the file COPYING. If not, write to the Free
+;; Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+;; MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; This file provides a native emms-info-method for SPC files. (well,
+;; actually the id666 tag embedded inside them). "Native" means a pure
+;; Emacs Lisp implementation instead of one relying on external tools
+;; or libraries.
+
+;;; Code:
+
+(require 'bindat)
+
+(defconst emms-info-native-spc--id666-magic-array
+  [#x53 #x4e #x45 #x53 #x2d #x53 #x50#x43 #x37 #x30 #x30 #x20 #x53 #x6f #x75 #x6e #x64 #x20 #x46 #x69 #x6c #x65 #x20 #x44 #x61 #x74 #x61 #x20 #x76 #x30 #x2e #x33 #x30]
+  "id666 header magic pattern `SNES-SPC700 Sound File Data v0.30'")
+
+(defconst emms-info-native-spc--id666-header-bindat-spec
+  '((file-identifier vec 33)
+    (eval (unless (equal last emms-info-native-spc--id666-magic-array)
+            (error "id666 framing mismatch: expected `%s', got `%s'"
+                   emms-info-native-spc--id666-magic-array
+                   last)))
+    (unused u16)
+    (has-id666 u8)
+    (revision u8)
+    (pc-reg u16)
+    (a-reg u8)
+    (x-reg u8)
+    (y-reg u8)
+    (psw-reg u8)
+    (sp-reg u8)
+    (res-reg u16)
+    (song-title strz 32)
+    (game-title strz 32)
+    (dumper strz 16)
+    (comment strz 32)
+    (date strz 11)
+    (fadeout vec 3)
+    (fadeout-length vec 5)
+    (artist strz 32))
+  "id666 header specification.
+
+Sources:
+
+- URL `https://ocremix.org/info/SPC_Format_Specification'
+- URL `https://picard-docs.musicbrainz.org/en/appendices/tag_mapping.html'")
+
+(defun emms-info-native-spc--decode-id666-header (filename)
+  "Read and decode id666 header from FILENAME."
+  (with-temp-buffer
+    (set-buffer-multibyte nil)
+    (insert-file-contents-literally filename nil 0 210)
+    (bindat-unpack emms-info-native-spc--id666-header-bindat-spec
+                   (buffer-string))))
+
+(defun emms-info-native-spc--decode-id666 (filename)
+  "Read and decode id666 metadata from FILENAME.
+Return metadata in a list of (FIELD . VALUE) cons cells, or nil
+in case of errors or if there were no known fields in FILENAME."
+  (condition-case nil
+      (let ((header (emms-info-native-spc--decode-id666-header filename)))
+	(when (= 26 (bindat-get-field header 'has-id666))
+	  (list
+	   (cons 'info-title (bindat-get-field header 'song-title))
+	   (cons 'info-album (bindat-get-field header 'game-title))
+	   (cons 'info-artist (bindat-get-field header 'artist))
+	   (cons 'info-composer (bindat-get-field header 'artist))
+	   (cons 'info-note (bindat-get-field header 'comment)))))
+    (error nil)))
+
+(provide 'emms-info-native-spc)
+
+;;; emms-info-native-spc.el ends here
diff --git a/emms-info-native.el b/emms-info-native.el
index 3e3e2d4..6c8bfff 100644
--- a/emms-info-native.el
+++ b/emms-info-native.el
@@ -51,6 +51,10 @@
 ;;   encryption are not supported.  Based on id3v2 Informal Standards,
 ;;   see URL `https://id3.org'.
 ;;
+;; - SPC files with extension `.spc' and id666 tags.  This is an audio
+;;   file based on a memory dump from an SPC700, a special audio chip
+;;   found within Super Nintendos.
+;;
 ;; Format detection is based solely on filename extension, which is
 ;; matched case-insensitively.
 
@@ -59,6 +63,7 @@
 (require 'bindat)
 (require 'cl-lib)
 (require 'emms-info)
+(require 'emms-info-native-spc)
 (require 'seq)
 (require 'subr-x)
 
@@ -954,6 +959,8 @@ strings."
            (emms-info-native--decode-flac-comments filename))
           ((eq stream-type 'mp3)
            (emms-info-native--decode-id3v2 filename))
+	  ((eq stream-type 'spc)
+	   (emms-info-native-spc--decode-id666 filename))
           (t nil))))
 
 (defun emms-info-native--find-stream-type (filename)
@@ -967,6 +974,7 @@ Return one of symbols `vorbis', `opus', `flac', or `mp3'."
           ((string-match ".opus$" filename) 'opus)
           ((string-match ".flac$" filename) 'flac)
           ((string-match ".mp3$" filename) 'mp3)
+	  ((string-match ".spc$" filename) 'spc)
           (t nil))))
 
 (provide 'emms-info-native)
diff --git a/emms.el b/emms.el
index 8581dfe..e003c72 100644
--- a/emms.el
+++ b/emms.el
@@ -376,7 +376,7 @@ Point will not be restored afterward."
   '("ogg" "mp3" "wav" "mpg" "mpeg" "wmv" "wma"
     "mov" "avi" "divx" "ogm" "ogv" "asf" "mkv"
     "rm" "rmvb" "mp4" "flac" "vob" "m4a" "ape"
-    "flv" "webm" "aif" "opus")
+    "flv" "webm" "aif" "opus" "spc")
   "A list of common formats which player definitions can use.")
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.