Index: /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1461)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 1462)
@@ -24,8 +24,10 @@
 import java.net.URLConnection;
 import java.net.UnknownHostException;
+import java.util.Arrays;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Date;
@@ -78,4 +80,5 @@
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.UrlLabel;
+import org.openstreetmap.josm.tools.AudioUtil;
 
 public class GpxLayer extends Layer {
@@ -205,12 +208,21 @@
                         Main.pref.put("markers.lastaudiodirectory", fc.getCurrentDirectory().getAbsolutePath());
 
-                    // FIXME: properly support multi-selection here.
-                    // Calling importAudio several times just creates N maker layers, which
-                    // is sub-optimal.
+                    MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", name), associatedFile, me);
                     File sel[] = fc.getSelectedFiles();
-                    if(sel != null)
-                        for (int i = 0; i < sel.length; i++)
-                            importAudio(sel[i]);
-
+                    if(sel != null) {
+                    	// sort files in increasing order of timestamp (this is the end time, but so long as they don't overlap, that's fine)
+                    	if (sel.length > 1) {
+                    		Arrays.sort(sel, new Comparator<File>() {
+                    			public int compare(File a, File b) {
+                    				return a.lastModified() <= b.lastModified() ? -1 : 1;
+                    			}
+                    		});
+                    	}
+                        double firstStartTime = sel[0].lastModified()/1000.0 /* ms -> seconds */ - AudioUtil.getCalibratedDuration(sel[0]);
+                        for (int i = 0; i < sel.length; i++) {
+                            importAudio(sel[i], ml, firstStartTime);
+                        }
+                    }
+                    Main.main.addLayer(ml);
                     Main.map.repaint();
                 }
@@ -836,16 +848,16 @@
      * (a) explict waypoints in the GPX layer, or
      * (b) named trackpoints in the GPX layer, or
-     * (c) (in future) voice recognised markers in the sound recording
-     * (d) a single marker at the beginning of the track
+     * (d) timestamp on the wav file
+     * (e) (in future) voice recognised markers in the sound recording
+     * (f) a single marker at the beginning of the track
      * @param wavFile : the file to be associated with the markers in the new marker layer
      */
-    private void importAudio(File wavFile) {
+    private void importAudio(File wavFile, MarkerLayer ml, double firstStartTime) {
         String uri = "file:".concat(wavFile.getAbsolutePath());
-        MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", name), associatedFile, me);
-
         Collection<WayPoint> waypoints = new ArrayList<WayPoint>();
         boolean timedMarkersOmitted = false;
         boolean untimedMarkersOmitted = false;
         double snapDistance = Main.pref.getDouble("marker.audiofromuntimedwaypoints.distance", 1.0e-3); /* about 25m */
+        WayPoint wayPointFromTimeStamp = null;
 
         // determine time of first point in track
@@ -916,7 +928,49 @@
         }
 
-        // (d) analyse audio for spoken markers here, in due course
-
-        // (e) simply add a single marker at the start of the track
+        // (d) use timestamp of file as location on track
+        if ((Main.pref.getBoolean("marker.audiofromwavtimestamps", false)) &&
+                data.tracks != null && ! data.tracks.isEmpty())
+        {
+            double lastModified = wavFile.lastModified() / 1000.0; // lastModified is in milliseconds
+            double duration = AudioUtil.getCalibratedDuration(wavFile);
+            double startTime = lastModified - duration;
+            startTime = firstStartTime + (startTime - firstStartTime) /  
+            	Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */);
+            WayPoint w1 = null;
+            WayPoint w2 = null;
+
+        	for (GpxTrack track : data.tracks) {
+        		if (track.trackSegs == null) continue;
+        		for (Collection<WayPoint> seg : track.trackSegs) {
+        			for (WayPoint w : seg) {
+                        if (startTime < w.time) {
+                            w2 = w;
+                            break;
+                        }
+                        w1 = w;
+                    }
+                    if (w2 != null) break;
+                }
+            }	
+
+            if (w1 == null || w2 == null) {
+            	timedMarkersOmitted = true;
+            } else {
+            	EastNorth eastNorth = w1.eastNorth.interpolate(
+            				w2.eastNorth,
+            				(startTime - w1.time)/(w2.time - w1.time));
+                wayPointFromTimeStamp = new WayPoint(Main.proj.eastNorth2latlon(eastNorth));
+                wayPointFromTimeStamp.time = startTime;
+                String name = wavFile.getName();
+                int dot = name.lastIndexOf(".");
+                if (dot > 0) { name = name.substring(0, dot); }
+                wayPointFromTimeStamp.attr.put("name", name);
+                waypoints.add(wayPointFromTimeStamp);
+            }        	
+        }
+        
+        // (e) analyse audio for spoken markers here, in due course
+
+        // (f) simply add a single marker at the start of the track
         if ((Main.pref.getBoolean("marker.audiofromstart") || waypoints.isEmpty()) &&
             data.tracks != null && ! data.tracks.isEmpty())
@@ -961,11 +1015,14 @@
             AudioMarker am = AudioMarker.create(w.latlon,
                     name, uri, ml, w.time, offset);
+            /* timeFromAudio intended for future use to shift markers of this type on synchronization */
+            if (w == wayPointFromTimeStamp) { 
+            	am.timeFromAudio = true; 
+            }
             ml.data.add(am);
         }
-        Main.main.addLayer(ml);
 
         if (timedMarkersOmitted) {
             JOptionPane.showMessageDialog(Main.parent,
-            tr("Some waypoints with timestamps from before the start of the track were omitted."));
+            tr("Some waypoints with timestamps from before the start of the track or after the end were omitted or moved to the start."));
         }
         if (untimedMarkersOmitted) {
Index: /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/AudioMarker.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/AudioMarker.java	(revision 1461)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/AudioMarker.java	(revision 1462)
@@ -20,5 +20,6 @@
     private static AudioMarker recentlyPlayedMarker = null;
     public  double syncOffset;
-
+    public boolean timeFromAudio = false; // as opposed to from the GPX track
+    
     /**
      * Verifies the parameter whether a new AudioMarker can be created and return
@@ -37,4 +38,5 @@
         this.audioUrl = audioUrl;
         this.syncOffset = 0.0;
+        this.timeFromAudio = false;
     }
 
Index: /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java	(revision 1461)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java	(revision 1462)
@@ -164,5 +164,5 @@
         if (ca == null) {
             /* Not close enough to track, or no audio marker found for some other reason */
-            JOptionPane.showMessageDialog(Main.parent, tr("You need to drag the play head near to the GPX track whose associated sound track you were playing."));
+            JOptionPane.showMessageDialog(Main.parent, tr("You need to drag the play head near to the GPX track whose associated sound track you were playing (after the first marker)."));
             endDrag(true);
         } else {
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java	(revision 1461)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java	(revision 1462)
@@ -36,4 +36,5 @@
     private JCheckBox audioMarkersFromUntimedWaypoints = new JCheckBox(tr("Explicit waypoints with time estimated from track position."));
     private JCheckBox audioMarkersFromNamedTrackpoints = new JCheckBox(tr("Named trackpoints."));
+    private JCheckBox audioMarkersFromWavTimestamps = new JCheckBox(tr("Modified times (time stamps) of audio files."));
     private JCheckBox audioMarkersFromStart = new JCheckBox(tr("Start of track (will always do this if no other markers available)."));
 
@@ -124,4 +125,15 @@
         gui.audio.add(audioMarkersFromNamedTrackpoints, GBC.eol().insets(10,0,0,0));
 
+        // audioMarkersFromWavTimestamps
+        audioMarkersFromWavTimestamps.addActionListener(new ActionListener(){
+            public void actionPerformed(ActionEvent e) {
+                if (!audioMarkersFromWavTimestamps.isSelected())
+                    audioMarkersFromWavTimestamps.setSelected(false);
+            }
+        });
+        audioMarkersFromWavTimestamps.setSelected(Main.pref.getBoolean("marker.audiofromwavtimestamps", false));
+        audioMarkersFromWavTimestamps.setToolTipText(tr("Create audio markers at the position on the track corresponding to the modified time of each audio WAV file imported."));
+        gui.audio.add(audioMarkersFromWavTimestamps, GBC.eol().insets(10,0,0,0));
+
         // audioMarkersFromStart
         audioMarkersFromStart.addActionListener(new ActionListener(){
@@ -166,4 +178,5 @@
         Main.pref.put("marker.audiofromuntimedwaypoints", audioMarkersFromUntimedWaypoints.isSelected());
         Main.pref.put("marker.audiofromnamedtrackpoints", audioMarkersFromNamedTrackpoints.isSelected());
+        Main.pref.put("marker.audiofromwavtimestamps", audioMarkersFromWavTimestamps.isSelected());
         Main.pref.put("marker.audiofromstart", audioMarkersFromStart.isSelected());
         Main.pref.put("audio.forwardbackamount", audioForwardBackAmount.getText());
Index: /trunk/src/org/openstreetmap/josm/tools/AudioUtil.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/tools/AudioUtil.java	(revision 1462)
+++ /trunk/src/org/openstreetmap/josm/tools/AudioUtil.java	(revision 1462)
@@ -0,0 +1,41 @@
+// License: GPL. Copyright 2009 by David Earl and others
+package org.openstreetmap.josm.tools;
+
+import java.io.IOException;
+import java.net.URL;
+import java.io.File;
+
+import javax.sound.sampled.AudioFormat;
+import javax.sound.sampled.AudioInputStream;
+import javax.sound.sampled.AudioSystem;
+
+import org.openstreetmap.josm.Main;
+
+
+/**
+ * Returns calibrated length of recording in seconds.
+ *
+ * @author David Earl <david@frankieandshadow.com>
+ *
+ */
+public class AudioUtil {
+	
+	static public double getCalibratedDuration(File wavFile) {
+        try {
+        	AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(
+        			new URL("file:".concat(wavFile.getAbsolutePath())));
+            AudioFormat audioFormat = audioInputStream.getFormat();
+            long filesize = wavFile.length();
+            double bytesPerSecond = audioFormat.getFrameRate() /* frames per second */
+                * audioFormat.getFrameSize() /* bytes per frame */;
+            double naturalLength = filesize / bytesPerSecond;
+            audioInputStream.close();
+            double calibration = Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */);
+            return naturalLength / calibration;
+        } catch (Exception e) {
+        	return 0.0;
+        }
+	}
+	
+}
+ 
