Beispiel #1
0
func UploadProc() {
	log.Println("starting upload proc")
	// read md5 to ID mapping
	// read ID to analysis mapping

	hasher := md5.New()
	e := echonest.New()
	if echonestkey != "" {
		e.Key = echonestkey
	}

	for r := range UploadChan {
		log.Println("got", len(r.Data), "bytes", r.Filetype, "add", r.Add, "playback", r.Playback)
		// md5 data and see if we have analysis already
		var m md5sum
		hasher.Write(r.Data)
		copy(m[:], hasher.Sum(nil))
		hasher.Reset()
		var id string
		var ok bool
		var a Analysis
		var url string
		var err error
		if id, ok = GetIDForChecksum(m); !ok {
			// log.Println("no id for md5", m)
			// if not upload it to analyzer.
			id, url, err = e.Upload(r.Filetype, r.Data)
			if err != nil {
				log.Println("error uploading track to EN", err)
				continue
			}
			// log.Println("got ID", id, "url", url, "err", err)

			// update md5 to id mapping
			AddIDForChecksum(m, id)
		}

		// if it comes back with an ID that we have, then great!
		// if not then fetch the detailed analysis
		// update id to analysis mapping
		if a, ok = GetSegmentsForID(id); !ok {
			a, err = DetailsForID(url, id)
			if err != nil {
				log.Println("error getting details from EN", err)
				continue
			}
			SetSegmentsForID(id, a)
		}

		go func() {
			// if it's marked "add" open data with sox sub process (for mp3, mp4, and m4a support) to get raw samples
			has := (a.Segments[0].File != "")
			if r.Add && !has {
				buf, err := openBuf(r.Data, r.Filetype)
				if err != nil {
					log.Println("couldn't get sox to run", err)
					return
				}
				// put raw samples into files
				for i := range a.Segments {
					filename := id + "_" + strconv.Itoa(a.Segments[i].Index)
					filename = path.Join(samplepath, filename)
					file, err := os.Create(filename)
					if err != nil {
						log.Println("couldn't open file", filename, err)
						continue
					}
					bytecount := int(a.Segments[i].Duration*float64(samplerate)) * 4 // 2 bytes per sample * 2 channels per frame
					// log.Println(a.segments[i].Duration, bytecount)
					_, err = file.Write(buf[:bytecount])
					if err != nil {
						log.Println("error writing sample", err)
					}
					file.Close()
					a.Segments[i].File = filename

				}
				// add to all segments
				// log.Println("adding to all segs")
				go func() { attributionChan <- en_tuple{id, playq{a.Artist, a.Title, r.Fma_url}} }()
				AddToAllSegs(a.Segments)
				// log.Println("done adding to all segs")
			}

			// if request is marked "playback" add the ID to the request queue
			if r.Playback {
				RequestQueue <- id
			}
		}()
	}
}
Beispiel #2
0
func RequestProc() {
	log.Println("starting RequestProc")
	e := echonest.New()
	if echonestkey != "" {
		e.Key = echonestkey
	}
	for r := range RequestQueue {
		log.Println("got request for ID", r)
		// see if we have analysis for this ID
		s, ok := GetSegmentsForID(r)
		if !ok {
			url, err := e.Analyze(r)
			// if we don't have analysis see if echonest does
			if err != nil {
				log.Println("error grabbing analysis from EN", err)
				continue
			}
			s, err = DetailsForID(url, r)
			if err != nil {
				log.Println("error grabbing analysis from EN", err)
				continue
			}
		}

		playqlock.Lock()
		// log.Println("putting",s.Artist,s.Title,"to queue")
		playqueue[playq{s.Artist, s.Title, ""}] = true
		playqlock.Unlock()

		// once we get analysis, start grabbing samples
		go func() {
			var ar AudioRequest
			allSegsLock.RLock()
			defer allSegsLock.RUnlock()
			expectedlen := float64(0)
			outlen := float64(0)
			var totdist float64
			for _, segment := range s.Segments {
				// var ss SegSortSlice
				//				m := make(map[SegmentID]bool)
				/*				var pitches = []int{12,12,12}
								// find highest three pitches in segment
								for note, p := range segment.Pitches[:] {
									if pitches[0] == 12 || p > segment.Pitches[pitches[0]] {
										pitches[2], pitches[1], pitches[0] = pitches[1], pitches[0], note
									} else if pitches[1] == 12 || p > segment.Pitches[pitches[1]] {
										pitches[2], pitches[1] = pitches[1], note
									} else if pitches[2] == 12 || p > segment.Pitches[pitches[2]] {
										pitches[2] = note
									}
								}

								for index, n := range pitches {
									i := 0
									for k := range m {
										m[k] = false
									}

									for _, v := range allSegs.Pitch[n].Segments[int(segment.Pitches[n] / allSegs.Pitch[n].Width)] {
										if _, ok := m[v]; (index == 0) || ok {
											i++
											m[v] = true
										}
									}
									if i <= 100 {
										break
									}
								}*/

				// ss.slice = make([]Segment, 0, len(m))
				closestDistance := float64(-1)
				var nearestSeg SegmentID
				for k, b := range allSegs.Segs {
					if allSegs.Segs[k].LoudnessMax > Loudness_min {
						thisDist := Distance(&segment, &b)
						if closestDistance < 0 || thisDist < closestDistance {
							fi, err := os.Stat(b.File)
							if err != nil || fi.IsDir() {
								log.Println("couldn't stat", b.File, "nil means IsDir", err)
								continue
							}
							closestDistance = thisDist
							nearestSeg = k
						}
					}
				}

				// ss.root = segment
				// sort.Sort(ss)
				// if len(ss.slice) > 0 {
				// for snum := 0; snum < len(ss.slice); snum++ {
				var outs Segment = allSegs.Segs[nearestSeg]
				totdist += outs.Distance
				// var mindist float64 = -1
				// var distcount int
				// for _, b := range allSegs.Segs {
				// 	outs = b
				// 	if mindist < 0 {
				// 		mindist = Distance(&segment, &outs)
				// 		log.Println("m", mindist)
				// 	} else if distcount < 10 {
				// 		if d := Distance(&segment, &outs); d < mindist {
				// 			mindist = d
				// 			distcount++
				// 			log.Println(mindist)
				// 		}
				// 	} else {
				// 		break
				// 	}
				// }
				outs.RootDuration = segment.Duration
				outs.RootLoudnessMax = segment.LoudnessMax
				outs.RootLoudnessStart = segment.LoudnessStart
				outlen += segment.Duration
				ar.segments = append(ar.segments, outs)
				// }
				// }
				expectedlen += segment.Duration
			}
			log.Println("avg distance", totdist/float64(len(ar.segments)))
			// log.Println(expectedlen, outlen)
			ar.artist = s.Artist
			ar.title = s.Title
			AudioQueue <- ar
		}()

	}
}