First time here? Check out the FAQ!

How can I extract the Sample accurate positions of Markers from an audio file?

+3 votes

When a gallery is created from a Sample file which has had Markers placed into it via the Sample Editor, the generated gallery features some sounds referring to MarkerSegments. They reference an algorithmically generated collection of what appears to be sample accurate positions for these embedded Markers. For example

((!PenDown sampleAndHold: !Marker) of: #( 32159 130015 382176 189086 )) / 189086

I would like to access the positions of Markers from a sample file without creating a gallery example. Is there a way in Smalltalk to fetch the sample positions of embedded Markers to define such a collection?

asked Apr 9, 2015 in Capytalk & Smalltalk by cristian-vogel (Master) (8,370 points)

2 Answers

+1 vote

As you point out, the easiest way to get the positions of all the markers in samples is to open the file in the Wave editor and create a Gallery; then you can select and copy those values.

To get the position of marker M1 in terms of samples, you would use the following Smalltalk:

'aFileWithMarkers.aif' asSamplesFile markers at: #M1

Sending asSamplesFile to the string name returns a SamplesFile object.  Sending markers to the SamplesFile object returns a dictionary of marker names as symbols to the sample on which that marker occurs.  To access the Dictionary, you say at: followed by the marker name as a symbol (the name of the marker preceded by the sharp sign).

answered Apr 11, 2015 by ssc (Savant) (117,620 points)
Thanks ssc, that's interesting. Could I list the contents of the dictionary, to find out how long it is, or what the symbol keys are? Is it  also possible index to index the dictionary with a position integer, rather than symbol?
If you want the positions of the markers in samples as a collection sorted in time order, you could use:

'aFileWithMarkers.aif' asSamplesFile markers values asSortedCollection

Once you have a collection, you can access it with integer indexes (starting at 1).
I was experimenting with the Smalltalk posted by SSC and it seems that the SortedCollection indexing starts at 0 for the first Marker in fact.
Just to clarify, Capytalk indexing is 0-based.  Smalltalk indexing starts with an index of 1.
Yes, timely reminder! Thanks SSC.
+3 votes

I tried looking into a file by using this code in a Numeric Display or parameter field. I also tried to convert the sample position into 0 to 1 range for use in SampleStart and so on, by dividing the sample fileduration in samples, but it doesnt seem to be calculated properly... investigating.

A little perusing of the Kyma X Revealed Smalltalk appendix reveals sampleFrames and so this is the final correct code to extract Marker positions and normalise them to (0,1) range.

You can remove the self debug once you are got it clear whats going on inside the collection.

| filename markerSamplePosition |
filename := 'aFileWithMarkers.aif' asSamplesFile.

self debugWithLabel: 'Names and sample positions of the Markers' value:  (filename markers) .

markerSamplePosition := !Marker of: (filename markers values asSortedCollection).

markerSamplePosition / (filename sampleFrames)


answered Apr 16, 2015 by cristian-vogel (Master) (8,370 points)
edited Apr 16, 2015 by cristian-vogel
TIPs: If you want to remove "dublicate" markers from the smalltalk SortedCollection you can use:

markerSamplePosition := !Marker of: (filename asSamplesFile markers values asSet asSortedCollection). ....  "the asSet  removes dublicates markers".

This is sometimes useful if you want to get rid of multiple markers on exactly the same samplePosition.


On my first tries i used the more self-explanatory version to get the correct range for the timeIndex Prototype.

markerSamplePosition / (filename sampleFileDuration samp removeUnits).

Of course Cristians version is more elegant:
markerSamplePosition / (filename sampleFrames)