Example #1
0
func (m *scannedMp3) crop(startSample, endSample int64, ips io.Reader, ops io.Writer) os.Error {
	//defer ips.Close() // FIXME: leave this to caller

	startSample = maxInt64(startSample, int64(-m.encDelay))
	endSample = minInt64(endSample, m.SampleCount()+int64(m.encPadding))

	maskAth := 0xff
	if startSample != 0 {
		maskAth &= MASK_ATH_KILL_NO_GAP_START
	}
	if endSample != m.SampleCount() {
		maskAth &= MASK_ATH_KILL_NO_GAP_END
	}

	firstFrameInclusive := max(0, int((startSample+int64(m.encDelay-minOverlapSamplesStart))/int64(m.samplesPerFrame)))
	lastFrameExclusive := min(m.musicFrameCount, int(
		(endSample+int64(m.encDelay+minOverlapSamplesEnd+m.samplesPerFrame-1))/int64(m.samplesPerFrame)))
	newEncDelay := m.encDelay + int(startSample-int64(firstFrameInclusive)*int64(m.samplesPerFrame))
	newEncPadding := int(int64(lastFrameExclusive-firstFrameInclusive)*
		int64(m.samplesPerFrame) - int64(newEncDelay) - (endSample - startSample))
	accessFrameRecord(firstFrameInclusive)

	needBytesFromReservoir := getBitResPtr()
	gotBytesFromReservoir := 0
	needPreFrames := 0
	for firstFrameInclusive-needPreFrames > 0 &&
		needBytesFromReservoir > gotBytesFromReservoir &&
		newEncDelay+1152 <= 4095 {
		needPreFrames++
		accessFrameRecord(firstFrameInclusive - needPreFrames)
		gotBytesFromReservoir += getMainDataSectionSize()
	}

	var resFrame []byte
	resFrameSize := 0
	firstFrameNum := firstFrameInclusive
	if needPreFrames == 0 {
		// force writing of PCUT tag frame
		needPreFrames = 1
	}
	if needPreFrames > 0 {
		firstFrameNum--
		newEncDelay += m.samplesPerFrame
		resFrame = make([]byte, MAX_MPAFRAME_SIZE)
		var newAbsStartSample int64 = startSample
		if m.startSample != UNKNOWN_START_SAMPLE {
			newAbsStartSample += m.startSample
		}
		resFrameSize = constructReservoirFrame(resFrame, m.firstFrameHeader,
			needBytesFromReservoir, newAbsStartSample)
	}

	seekTable := make([]byte, 100)
	var avgBytesPerFrame, avgBytesPerSecnd, avgkbps float32
	musiLen := 0
	{ // calculate seek table
		accessFrameRecord(firstFrameInclusive)
		ofs00 := getFrameFileOfs() - resFrameSize
		accessFrameRecord(max(0, lastFrameExclusive-1))
		ofsXX := getFrameFileOfs() + getFrameSize()
		musiLen = ofsXX - ofs00
		avgBytesPerFrame = float32(ofsXX-ofs00) /
			float32(lastFrameExclusive-firstFrameInclusive)
		avgBytesPerSecnd = avgBytesPerFrame * float32(m.firstFrameHeader.SampleRate()) /
			float32(m.firstFrameHeader.SamplesPerFrame())
		avgkbps = avgBytesPerSecnd / float32(125)
		for i := 0; i < 100; i++ {
			fidx := round(float32(firstFrameInclusive+i+1) / 101.0 *
				float32(lastFrameExclusive-firstFrameInclusive))
			accessFrameRecord(max(0, fidx))
			seekTable[i] = byte(round(float32(getFrameFileOfs()-ofs00) * float32(255) /
				float32(ofsXX-ofs00)))
		}
	}

	frameBuff := make([]byte, MAX_MPAFRAME_SIZE)
	fl := XingInfoLameTagFrame.createHeaderFrame(firstFrameHeader, isVBR, avgkbps,
		lastFrameExclusive-firstFrameNum, musiLen, 50, seektable, newEncDelay,
		newEncPadding, xiltFrame, frameBuff, 0, maskATH)
	ops.write(frameBuff, 0, fl)
	filepos := 0
	sideInfoSize := firstFrameHeader.getSideInfoSize()
	bitRes := 0

	if needPreFrames > 0 {
		reservoir = make([]byte, 511)
		if needBytesFromReservoir > 0 {
			for fi := firstFrameInclusive - needPreFrames; fi < firstFrameInclusive; fi++ {
				accessFrameRecord(fi)
				tmp := getFrameFileOfs()
				ips.skip(tmp - filepos)
				filepos = tmp
				fl = getFrameSize()
				readFully(ips, frameBuff, 0, fl)
				filepos += fl
				mdss := getMainDataSectionSize()
				if mdss >= 511 {
					copy(reservoir, frameBuff[fl-511:])
					// System.arraycopy(frameBuff, fl - 511, reservoir, 0, 511);
				} else {
					move := 511 - mdss
					copy(reservoir[:move], reservoir[511-move:])
					copy(reservoir[move:], frameBuff[fl-mdss:])
					// System.arraycopy(reservoir, 511 - move, reservoir, 0, move);
					// System.arraycopy(frameBuff, fl - mdss, reservoir, move, mdss);
				}
			}
			copy(resFrame[resFrameSize-needBytesFromReservoir:resFrameSize], reservoir[511-needBytesFromReservoir:])
			// System.arraycopy(reservoir, 511 - needBytesFromReservoir, resFrame,
			//         resFrameSize - needBytesFromReservoir, needBytesFromReservoir);
		}
		ops.write(resFrame, 0, resFrameSize)
		bitRes = needBytesFromReservoir
	}

	for fi := firstFrameInclusive; fi < lastFrameExclusive; fi++ {
		accessFrameRecord(fi)
		tmp := getFrameFileOfs()
		ips.skip(tmp - filepos)
		filepos = tmp
		fl = getFrameSize()
		readFully(ips, frameBuff, 0, fl)
		filepos += fl
		tmp = getBitResPtr()
		if tmp > bitRes {
			silenceFrame(frameBuff, 0, sideInfoSize)
		}
		ops.Write(frameBuff[:fl])
		tmp = getMainDataSectionSize()
		bitRes = min(bitRes+tmp, maxRes)
	}
}