Redi.MaxMod and SID files.

BlitzMax Forums/BlitzMax Programming/Redi.MaxMod and SID files.

Hi there,

I'm using the above module in conjunction with the SID.SidStream module to enable playback of both OGG and SID files within my application.

Ideally what i'd like it to do is play the SID until the end and the move onto the next file; but it seems i've hit a problem.

The current location and length values in MaxMod don't seem to work when we're reading in a SID file.

Is there any way around this issue?

I realise it could be because it's using the streaming functionality (hence it doesn't know how long the file is until it hits the end), but what seems to happen is that the SID loops indefinately.

Any clues anyone?

Cheers

Pete

No idea about SID files, but doesn't MaxMod's tMusic.Geti(MM_ISPLAYING) work?

Hi WiredWorm

The SID module is gmans baby, but AFAIK there is no way in SIDPlay to get the actual length of the music, I think its todo with the way SID files work, could be wrong tho.

I'd say give gman a shout, see what he thinks.

I remember something about a song length database for sid files, cant seem to find it ATM tho.

Thanks for the comments GfK and REDi.

I've loaded some SID files into SidPlay2 which I believe uses an updated version of the libsidplay.dll file and I notice that this also seems to have a similar issue.

So, I think you are quite correct - I think the problem I am seeing is a limitation of the file format more than anything. For now I have put an option in whereby the user can force the next track to start playing.

GfK, MM_ISPLAYING doesn't seem to work.

Cheers

Pete

I found this http://www.geocities.com/siliconvalley/lakes/5147/sidplay/sldb.html which includes a source code download for a utility which will attempt to determine the SID length.

Unfortunately it seems to be coded in C++ and i've got no clue how i'd make use of it in Blitz.

Unless of course some kind soul can give some pointers?

Cheers

Pete

currently there is no way in libsidplay2 (which the mod is based on) to determine the length of SID tunes. there is a database and some code at the link posted by WiredWorm, but the code is based on the original libsidplay and not compatible with libsidplay2.

at this time, the only option that i know of is to write some custom code that uses the verbose file available at the above link to lookup the file and the lengths based on filename. i have thought about it how i would do this... i will see if i can add something to the mod to optionally allow use of a verbose file. i will give a better answer tonight when i can get at my code.

I wrote a gui for playing .Sid files a couple of months back which I planned to rewrite creating the GUI with LogicGUI so the interface is better. I had the same kind of problem with knowing when a .Sid file has finished so kind of put the project on hold waiting to see if there was any way round the problem.

As has been confirmed already the problem isn't with Maxmod of gman's sidplay library but rather the botchy way the sid tunes are ripped out of C64 games and don't actually contain data structures with the lengths of each embedded tune to work with. Bearing in mind the sound routines on these tunes were written in 6510 assembler in the early eighty's and were designed for only playing music within the game itself then it's understandable to an extent.

What would be awesome would be someone to write a powerful conversion tool to convert a .Sid tune into a .S64 tune and reformat the data so the times for each piece of music are in it to which it could collect from an internet site SQL database or similar. Then it would just need gman and redi to modify the source to their modules slightly to understand the new format and put in the ability to pull out the playback times of each tune.

We can all hope as the C64 music days were fantastic.

Oh yeah, if anyone wants to mess with the Sidplayer I wrote then it's in my project log. The interface isn't great but it works fine and I'll put the source code on my website as soon as I get round to it if it'll help someone else out with using the blitz mods.

Thanks for the comments Xerra and Gman. For the moment i've done a couple of things. Firstly i've modified the config file so we can switch the ability to play SID tunes on and off without having to recompile the binary; i've also put in place the ability to hit the M key to automatically launch into the next song.

I may look at implementing the length database at some point but i've got a deadline to work to and at the moment the SID functionality isn't essential. So if I get time at the end then i'll look at it.

In the meantime someone else might come up with a solution :)

Would you mind posting your OGG streaming code? I'd love to see how you do it, and I don't have much time these days to delve into this sort of thing.

Getting this after download and install the sid.mod

Compile Error
Can't find interface for module 'redi.maxmod'

but the maxmod.module is installed too, but the folder is named as

mod/maxmod.mod?????

The MAXMOD is the Version 1.21

MainframeOSX,

Redi posted this in his MaxMod topic:

SuperStrict 

Rem
bbdoc: SID Stream for MaxMod
End Rem
Module SID.SIDStream

ModuleInfo "Version: 1.04"
ModuleInfo "Name: SID.SIDStream"
ModuleInfo "Description: MaxMod SID streaming player"
ModuleInfo "License: GPL (libsidplay2 is GPL)"
ModuleInfo "Author: gman"
ModuleInfo "Credit: REDi, author of MaxMod (http://www.redi.me.uk/forum/index.php)"
ModuleInfo "History: 2006/7/16 - GG Initial Release"
ModuleInfo "History: 2006/8/1 - REDi Updated for MaxMod v1.9"
ModuleInfo "History: 2006/8/29 - Updated for MaxMod v1.10 by Matt Smith (thank you)"
ModuleInfo "History: 2006/9/5 - Updated for MaxMod v1.11 by REDi (thank you)"
ModuleInfo "History: 2006/10/19 - Recompiled for MaxMod v1.15"
ModuleInfo "History: 2007/02/19 - Recompiled for MaxMod v1.16 by REDi"

Import MaxMod.aMusic
Import SID.SIDPlay
Import BRL.StandardIO

' This adds it to the MaxMod Loader
MaxModLoader.Create(MaxMod_Loader_SID,"SID ~q.sid~q","sid")
Function MaxMod_Loader_SID:TMusic(File:String)
	Local SID:TMusic = SIDStream.Load(File)
	Return SID
EndFunction

Rem
bbdoc: MaxMod SID Stream
End Rem
Type SIDStream Extends TMusic

	' SIDPlayer pointers
	Field resid:Byte Ptr
	Field tune:Byte Ptr
	Field player:Byte Ptr
	
	Field Track:Short
	Field Bits:Short
	Field Channels:Short
	Field clockSpeed:Int

	Rem
	bbdoc: Loads a SID file and returns an audio sample for playback
	returns: an instance of TAudioSample
	about: Filename => path and name of file to load<BR>
	Track => the track within the file to return a sample for<BR>
	Rate => sample rate to play the sample at<BR>
	format => sample format<BR>
	clockSpeed => SID sample playback clock speed
	EndRem						
	Function Load:SIDStream(Filename:String, Track:Short=1, Rate:Int=44100, format:Int=MM_STEREO16, clockSpeed:Int=SID2_CLOCK_PAL)
			
		Local file:Byte[]=LoadByteArray(Filename)

		Local This:SIDStream = New SIDStream
		
		' make sure we have the file
		If file
			This.clockSpeed=clockSpeed
			
			' load the SID file into the tune
			This.tune=createSidTune()			
			
			If Not This.tune Then RuntimeError "SIDStream.Load(): Unable to create SidTune"
			
			If Not SidTune_Read(This.tune,file,file.length) Then RuntimeError "SIDStream.Load(): Unable To load "+filename
			file=Null
					
			' select the track within the SID file
			If Not This.SelectTrack(Track) Then RuntimeError "SIDStream.Load(): Unable to select track "+Track
										
			This.channels=sid2_mono
			If format=MM_STEREO8 Or format=MM_STEREO16 Then This.channels=sid2_stereo
		
			' bump down to mono if the sample is mono	
			If This.channels=MM_STEREO8 And Not SidTune_IsStereo(This.tune)
				Select format
					Case MM_STEREO8
						format=MM_MONO8
					Case MM_STEREO16
						format=MM_MONO16
				EndSelect
				This.channels=sid2_mono
			EndIf
			
			This.bits=8
			If format<>MM_MONO8 And format<>MM_STEREO8 Then This.bits=16
		 
			This.STREAM_FORMAT=format
			This.Sample_Rate=Rate
			This.bits=16
		
			' create the ReSIDBuilder
			This.resid=createReSIDBuilder("MaxMod Load SID")
			If Not This.resid Then RuntimeError "SIDStream.Load(): Unable to create ReSIDBuilder"
										
			' create the player for decoding
			This.player=createSidPlay2(This.resid)
			
			' set the player options
			If Not SidPlay2_SetFrequency(This.player,rate) Then RuntimeError "SIDStream.Load(): Unable to set rate "+rate
			If Not SidPlay2_SetBits(This.player,This.bits) Then RuntimeError "SIDStream.Load(): Unable to set bits "+This.bits
			If Not SidPlay2_SetPlayback(This.player,This.channels) Then RuntimeError "SIDStream.Load(): Unable to set format "+format
			If Not SidPlay2_SetClockSpeed(This.player,This.clockSpeed) Then RuntimeError "SIDStream.Load(): Unable to set clockSpeed "+This.clockSpeed
			
			' load the tune into the player
			If SidPlay2_Load(This.player,This.tune)<>0 Then RuntimeError "SIDStream.Load(): Unable to load tune into the player"
			
			Return This					
		Else
			Return Null		
		EndIf	
	EndFunction

	Method Stop()
'		Super.Stop()
		SidPlay2_Load(player,tune)
	EndMethod

	Rem
	bbdoc: Returns the current track being played
	End Rem
	Method CurrentTrack:Short()
		Return Track
	EndMethod

	Rem
	bbdoc: Returns the total tracks within the SID
	End Rem
	Method GetTrackCount:Short()
		Return SidTuneInfo_songs(SidTune_getInfo(tune))
	EndMethod

	Rem
	bbdoc: Selects a track within the SID to play
	returns: True if successful
	End Rem
	Method SelectTrack:Int(track:Short=1)
		' select the track within the SID file
		Local playing:Int
		If PlayStatus = True Then playing = True
		If SidTune_SelectSong(tune,track)=track Then 
'			If playing Then Stop
			SidPlay2_Load(player,tune)
			Self.Track=track
'			If playing Then Play
			Return True
		Else
			Return False
		EndIf
	EndMethod

	Method Delete()
		' cleanup the libsidplay objects
		deleteSidPlay2(player)
		deleteSidTune(tune)
		deleteReSIDBuilder(resid)	
	EndMethod
	
	' this method gets called when the buffer needs filling
	Method FillBuffer(SoundData:Int,Length:Int)
		If Not Length Return
		Global count:Int
		If Not SidPlay2_Play(player,Short Ptr(SoundData),Length) Then RuntimeError "SIDStream.FillBuffer(): Unable to process sample data"
		count:+Length												
	EndMethod
	
EndType


Thanks Matt! :)

OK. It compile the module. I am using the sample of the Sidplayer
this is now:

Building .LoadSIDSample
Compiling:.LoadSIDSample.bmx
Linking:.LoadSIDSample
/usr/bin/ld: archive: /Developer/BlitzMax/lib/libsidplay.a has no table of contents, add one with ranlib(1) (can't load from it)
/usr/bin/ld: archive: /Developer/BlitzMax/lib/libresid_builder.a has no table of contents, add one with ranlib(1) (can't load from it)
collect2: ld returned 1 exit status
Build Error: Failed to link /Developer/BlitzMax/mod/sid.mod/sidsample.mod/doc/.LoadSIDSample
Process complete

any idea, or have i compile the Sidlib2 for MACOS X. The Lib is in the Lib Folder!