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) } }