Ignore:
Timestamp:
2009-03-05T14:27:58+01:00 (15 years ago)
Author:
david
Message:

first cut of creation of audio markers from timestamps on a set of audio files with clock synced to GPS.

Location:
trunk/src/org/openstreetmap/josm/gui
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java

    r1435 r1462  
    2424import java.net.URLConnection;
    2525import java.net.UnknownHostException;
     26import java.util.Arrays;
    2627import java.util.ArrayList;
    2728import java.util.Collection;
    2829import java.util.Collections;
    2930import java.util.Comparator;
     31import java.util.Iterator;
    3032import java.util.LinkedList;
    3133import java.util.Date;
     
    7880import org.openstreetmap.josm.tools.ImageProvider;
    7981import org.openstreetmap.josm.tools.UrlLabel;
     82import org.openstreetmap.josm.tools.AudioUtil;
    8083
    8184public class GpxLayer extends Layer {
     
    205208                        Main.pref.put("markers.lastaudiodirectory", fc.getCurrentDirectory().getAbsolutePath());
    206209
    207                     // FIXME: properly support multi-selection here.
    208                     // Calling importAudio several times just creates N maker layers, which
    209                     // is sub-optimal.
     210                    MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", name), associatedFile, me);
    210211                    File sel[] = fc.getSelectedFiles();
    211                     if(sel != null)
    212                         for (int i = 0; i < sel.length; i++)
    213                             importAudio(sel[i]);
    214 
     212                    if(sel != null) {
     213                        // sort files in increasing order of timestamp (this is the end time, but so long as they don't overlap, that's fine)
     214                        if (sel.length > 1) {
     215                                Arrays.sort(sel, new Comparator<File>() {
     216                                        public int compare(File a, File b) {
     217                                                return a.lastModified() <= b.lastModified() ? -1 : 1;
     218                                        }
     219                                });
     220                        }
     221                        double firstStartTime = sel[0].lastModified()/1000.0 /* ms -> seconds */ - AudioUtil.getCalibratedDuration(sel[0]);
     222                        for (int i = 0; i < sel.length; i++) {
     223                            importAudio(sel[i], ml, firstStartTime);
     224                        }
     225                    }
     226                    Main.main.addLayer(ml);
    215227                    Main.map.repaint();
    216228                }
     
    836848     * (a) explict waypoints in the GPX layer, or
    837849     * (b) named trackpoints in the GPX layer, or
    838      * (c) (in future) voice recognised markers in the sound recording
    839      * (d) a single marker at the beginning of the track
     850     * (d) timestamp on the wav file
     851     * (e) (in future) voice recognised markers in the sound recording
     852     * (f) a single marker at the beginning of the track
    840853     * @param wavFile : the file to be associated with the markers in the new marker layer
    841854     */
    842     private void importAudio(File wavFile) {
     855    private void importAudio(File wavFile, MarkerLayer ml, double firstStartTime) {
    843856        String uri = "file:".concat(wavFile.getAbsolutePath());
    844         MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", name), associatedFile, me);
    845 
    846857        Collection<WayPoint> waypoints = new ArrayList<WayPoint>();
    847858        boolean timedMarkersOmitted = false;
    848859        boolean untimedMarkersOmitted = false;
    849860        double snapDistance = Main.pref.getDouble("marker.audiofromuntimedwaypoints.distance", 1.0e-3); /* about 25m */
     861        WayPoint wayPointFromTimeStamp = null;
    850862
    851863        // determine time of first point in track
     
    916928        }
    917929
    918         // (d) analyse audio for spoken markers here, in due course
    919 
    920         // (e) simply add a single marker at the start of the track
     930        // (d) use timestamp of file as location on track
     931        if ((Main.pref.getBoolean("marker.audiofromwavtimestamps", false)) &&
     932                data.tracks != null && ! data.tracks.isEmpty())
     933        {
     934            double lastModified = wavFile.lastModified() / 1000.0; // lastModified is in milliseconds
     935            double duration = AudioUtil.getCalibratedDuration(wavFile);
     936            double startTime = lastModified - duration;
     937            startTime = firstStartTime + (startTime - firstStartTime) / 
     938                Main.pref.getDouble("audio.calibration", "1.0" /* default, ratio */);
     939            WayPoint w1 = null;
     940            WayPoint w2 = null;
     941
     942                for (GpxTrack track : data.tracks) {
     943                        if (track.trackSegs == null) continue;
     944                        for (Collection<WayPoint> seg : track.trackSegs) {
     945                                for (WayPoint w : seg) {
     946                        if (startTime < w.time) {
     947                            w2 = w;
     948                            break;
     949                        }
     950                        w1 = w;
     951                    }
     952                    if (w2 != null) break;
     953                }
     954            }   
     955
     956            if (w1 == null || w2 == null) {
     957                timedMarkersOmitted = true;
     958            } else {
     959                EastNorth eastNorth = w1.eastNorth.interpolate(
     960                                        w2.eastNorth,
     961                                        (startTime - w1.time)/(w2.time - w1.time));
     962                wayPointFromTimeStamp = new WayPoint(Main.proj.eastNorth2latlon(eastNorth));
     963                wayPointFromTimeStamp.time = startTime;
     964                String name = wavFile.getName();
     965                int dot = name.lastIndexOf(".");
     966                if (dot > 0) { name = name.substring(0, dot); }
     967                wayPointFromTimeStamp.attr.put("name", name);
     968                waypoints.add(wayPointFromTimeStamp);
     969            }           
     970        }
     971       
     972        // (e) analyse audio for spoken markers here, in due course
     973
     974        // (f) simply add a single marker at the start of the track
    921975        if ((Main.pref.getBoolean("marker.audiofromstart") || waypoints.isEmpty()) &&
    922976            data.tracks != null && ! data.tracks.isEmpty())
     
    9611015            AudioMarker am = AudioMarker.create(w.latlon,
    9621016                    name, uri, ml, w.time, offset);
     1017            /* timeFromAudio intended for future use to shift markers of this type on synchronization */
     1018            if (w == wayPointFromTimeStamp) {
     1019                am.timeFromAudio = true;
     1020            }
    9631021            ml.data.add(am);
    9641022        }
    965         Main.main.addLayer(ml);
    9661023
    9671024        if (timedMarkersOmitted) {
    9681025            JOptionPane.showMessageDialog(Main.parent,
    969             tr("Some waypoints with timestamps from before the start of the track were omitted."));
     1026            tr("Some waypoints with timestamps from before the start of the track or after the end were omitted or moved to the start."));
    9701027        }
    9711028        if (untimedMarkersOmitted) {
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/AudioMarker.java

    r1169 r1462  
    2020    private static AudioMarker recentlyPlayedMarker = null;
    2121    public  double syncOffset;
    22 
     22    public boolean timeFromAudio = false; // as opposed to from the GPX track
     23   
    2324    /**
    2425     * Verifies the parameter whether a new AudioMarker can be created and return
     
    3738        this.audioUrl = audioUrl;
    3839        this.syncOffset = 0.0;
     40        this.timeFromAudio = false;
    3941    }
    4042
  • trunk/src/org/openstreetmap/josm/gui/layer/markerlayer/PlayHeadMarker.java

    r1415 r1462  
    164164        if (ca == null) {
    165165            /* Not close enough to track, or no audio marker found for some other reason */
    166             JOptionPane.showMessageDialog(Main.parent, tr("You need to drag the play head near to the GPX track whose associated sound track you were playing."));
     166            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)."));
    167167            endDrag(true);
    168168        } else {
  • trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java

    r1245 r1462  
    3636    private JCheckBox audioMarkersFromUntimedWaypoints = new JCheckBox(tr("Explicit waypoints with time estimated from track position."));
    3737    private JCheckBox audioMarkersFromNamedTrackpoints = new JCheckBox(tr("Named trackpoints."));
     38    private JCheckBox audioMarkersFromWavTimestamps = new JCheckBox(tr("Modified times (time stamps) of audio files."));
    3839    private JCheckBox audioMarkersFromStart = new JCheckBox(tr("Start of track (will always do this if no other markers available)."));
    3940
     
    124125        gui.audio.add(audioMarkersFromNamedTrackpoints, GBC.eol().insets(10,0,0,0));
    125126
     127        // audioMarkersFromWavTimestamps
     128        audioMarkersFromWavTimestamps.addActionListener(new ActionListener(){
     129            public void actionPerformed(ActionEvent e) {
     130                if (!audioMarkersFromWavTimestamps.isSelected())
     131                    audioMarkersFromWavTimestamps.setSelected(false);
     132            }
     133        });
     134        audioMarkersFromWavTimestamps.setSelected(Main.pref.getBoolean("marker.audiofromwavtimestamps", false));
     135        audioMarkersFromWavTimestamps.setToolTipText(tr("Create audio markers at the position on the track corresponding to the modified time of each audio WAV file imported."));
     136        gui.audio.add(audioMarkersFromWavTimestamps, GBC.eol().insets(10,0,0,0));
     137
    126138        // audioMarkersFromStart
    127139        audioMarkersFromStart.addActionListener(new ActionListener(){
     
    166178        Main.pref.put("marker.audiofromuntimedwaypoints", audioMarkersFromUntimedWaypoints.isSelected());
    167179        Main.pref.put("marker.audiofromnamedtrackpoints", audioMarkersFromNamedTrackpoints.isSelected());
     180        Main.pref.put("marker.audiofromwavtimestamps", audioMarkersFromWavTimestamps.isSelected());
    168181        Main.pref.put("marker.audiofromstart", audioMarkersFromStart.isSelected());
    169182        Main.pref.put("audio.forwardbackamount", audioForwardBackAmount.getText());
Note: See TracChangeset for help on using the changeset viewer.