Exemplo n.º 1
0
func loadSong(filename string) (song Song, err error) {
	f, err := os.Open(filename)
	if err != nil {
		return
	}
	song.Info = make(map[string]string)
	id3info := id3.Read(f)
	if id3info != nil {
		song.Info["title"] = id3info.Name
		song.Info["artist"] = id3info.Artist
	}
	song.Info["filename"] = filename
	f.Close()
	arguments := []string{filename}
	arguments = append(arguments, soxFormat...)
	arguments = append(arguments, "-")
	arguments = append(arguments, soxTrim(30, 4)...)
	cmd := exec.Command("sox", arguments...)
	buffer := new(bytes.Buffer)
	cmd.Stdout = buffer
	err = cmd.Run()
	if err != nil {
		return Song{}, err
	}
	samples := make([]float64, buffer.Len())
	for i, sample := range buffer.Bytes() {
		samples[i] = float64(sample)
	}
	spectrogram := spectral.Compute(samples, 1024, 0.75)
	statistics := spectrogram.Stats(22050)
	features := []string{"cutoffFreq", "energyCV", "maxEnergyFreq", "maxVarFreq"}
	song.Features = make([]float64, 0, len(features))
	for _, stat := range features {
		song.Features = append(song.Features, statistics[stat])
	}
	song.Features = append(song.Features, spectrogram.LogFreq...)
	return
}
Exemplo n.º 2
0
// MusicPick lets the user pick playlist tracks from local files
func MusicPick(inDirectory, outDirectory string, tracks Tracks) (err error) {

	var id3Files []*id3.File
	var filePaths []string

	// Traverse all folders inside inDirectory and load all music files
	walkFunc := func(path string, info os.FileInfo, err error) error {

		if err != nil {
			return err
		}

		stat, err := os.Stat(path)
		if err != nil {
			return err
		}

		// We only open files
		if stat.IsDir() {
			return nil
		}

		// Only open .mp3 and .flac files
		if !strings.HasSuffix(strings.ToLower(path), ".mp3") && !strings.HasSuffix(strings.ToLower(path), ".flac") {
			return nil
		}

		// Open file
		fd, err := os.Open(path)
		if err != nil {
			return err
		}
		defer fd.Close()

		// Read id3
		id3File := id3.Read(fd)
		if id3File == nil {
			errorf("could not read id3 tags\n")
			return nil
		}

		// Add to slice
		id3Files = append(id3Files, id3File)
		filePaths = append(filePaths, path)

		return err
	}
	if err = filepath.Walk(inDirectory, walkFunc); err != nil {
		return
	}

	// Go through each track and try to find it.
	for i, x := range tracks {

		fmt.Fprintf(color.Output, "[%d / %d] Locating track: %s Artist: %s\n", i, len(tracks)-1, boldS(x.Name), boldS(x.ArtistName))

		var matchedID3s []*id3.File
		var matchedFilepaths []string
		for k, y := range id3Files {

			// Match algorithm
			a, b := strings.ToLower(y.Artist), strings.ToLower(x.ArtistName)
			if strings.Contains(a, b) || strings.Contains(b, a) {
				matchedID3s = append(matchedID3s, y)
				matchedFilepaths = append(matchedFilepaths, filePaths[k])
			}

		}

		// Continue to next track if we got no results
		if len(matchedID3s) < 1 {
			logf("No matches\n")
			continue
		}
	}

	return
}
Exemplo n.º 3
0
func getSongs() []SongRecord {
	addfilechannel := make(chan SongRecord, 100)

	var w sync.WaitGroup

	for _, playlistRec := range IcerayCfg.Playlist {

		fext := strings.ToLower(filepath.Ext(playlistRec.Path))
		if fext == ".xspf" {
			// process XML playlist file
		} else if fext == ".m3u" {
			// process m3u playlist file
		} else {
			w.Add(1)
			go folderSearch(playlistRec.Path, playlistRec.Subdirs, addfilechannel, &w)
		}
	}

	// wait for song search(es) to finish up
	w.Wait()
	close(addfilechannel)

	var songs []SongRecord

	for mfile := range addfilechannel {

		// Read in MP3 info and save it

		fd, err := os.Open(mfile.fullpath)
		defer fd.Close()

		if err != nil {
			log.Println("Problem opening: " + mfile.fullpath)
			continue
		}

		// Read in MP3 tags
		mp3tags := id3.Read(fd)

		if mp3tags == nil {
			log.Println("Problems getting MP3 tags for " + mfile.fullpath)
			continue
		}

		if mp3tags.Artist == "" {
			log.Println("Artist tag missing for " + mfile.fullpath)
			continue
		}

		if mp3tags.Name == "" {
			log.Println("Song tag missing for " + mfile.fullpath)
			continue
		}

		mfile.artist = mp3tags.Artist
		mfile.title = mp3tags.Name

		songs = append(songs, mfile)
	}

	if IcerayCfg.Music.Shuffle {
		// Now (linear) shuffle it
		sc := len(songs)
		for i := range songs {
			j := randGen.Intn(sc)
			songs[i], songs[j] = songs[j], songs[i]
		}
	}

	return songs
}