好久没写BLOG了,送上一份原创的DELPHI版MP3切割,splitMp3为切割函数,支持按时间切割和按大小切割。望大家支持。

参考VC的资料编写的MP3切割DELPHI版单元.

unit UnitMp3DataUtil;

{
MP3 Cut Unit.
@author Jim Wu
2009-08
}

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls;
type
  Mp3SplitMode = (Mp3SplitByTime, Mp3SplitByDateLength);
  TMp3DataInfo = packed record
    isMp3: Boolean;
    bitrate: Integer;
    sampleRate: Integer;
    isMono: Boolean;
    isVBR: Boolean;
  end;

function readMp3Head(fileName: string): TMp3DataInfo;
  function splitMp3(mode: Mp3SplitMode; length: Integer; fr: TFileStream; writeFileName: string; var actualLength: Integer; var actualMillisecond: Integer): integer;

const
  mpegBitrateTable: array[1..2,1..3,1..14] of Integer=(
    (
      ( 32, 64, 96,128,160,192,224,256,288,320,352,384,416,448),
      ( 32, 48, 56, 64, 80, 96,112,128,160,192,224,256,320,384),
      ( 32, 40, 48, 56, 64, 80, 96,112,128,160,192,224,256,320)
    ),
    (
      ( 32, 48, 56, 64, 80, 96,112,128,144,160,176,192,224,256),
      (  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160),
      (  8, 16, 24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160)
    )
  );
  samplingRateTable: array[1..3,0..2] of Integer=(
    (44100,48000,32000),
    (22050,24000,16000),
    (11025,12000,8000)
  );
  frameLengthTable: array[1..2,1..3] of Integer=(
    (48000,144000,144000),
    (24000, 72000, 72000)
  );
  samplesPerFrameTable: array[1..2,1..3] of Integer=(
    ( 384,1152,1152),
    ( 384,1152, 576)
  );

implementation

function readMp3Head(fileName: string): TMp3DataInfo;
var
  binData: array [0..3] of Byte;
  tempDate: array [0..3] of Byte;
  fr: TFileStream;
  mpegPadding: Byte;
  mpegVersion: Double;
  mpegLayer: Byte;
  seekDataLength: Integer;
begin
  fr := TFileStream.Create(fileName, fmOpenRead);
  fr.Read(binData, 4);
  if (binData[0] = $49) and (binData[1] = $44) and (binData[2] = $33) then
  begin //readMp3Head
    fr.Seek(2, soFromCurrent);
    fr.Read(tempDate, 4); //解析长度
    seekDataLength := tempDate[0] and $7F shl 21 + tempDate[1] and $7F shl 14 + tempDate[2] and $7F shl 7 + tempDate[3] and $7F;
    fr.Seek(seekDataLength, soFromCurrent);
    fr.Read(binData, 4);
  end;

if binData[0] = $FF then //DATA Frame
  begin
    case binData[1] shr 3 and $3 of
    0: mpegVersion := 2.5;
    1: ; //reserved
    2: mpegVersion := 2;
    3: mpegVersion := 1;
    end;

mpegLayer := 4 - (binData[1] shr 1 and $3);

result.bitrate := mpegBitrateTable[Trunc(mpegVersion)][mpegLayer][binData[2] shr 4 and $F];
    result.sampleRate := samplingRateTable[Trunc(mpegVersion+0.5)][binData[2] shr 2 and $3];
    mpegPadding := binData[2] shr 1 and $1;

if binData[3] shr 6 and $3 = 3 then
      result.isMono := True
    else
      Result.isMono := False;

fr.Seek(32, soFromCurrent); //read Xing(VBR) Flag
    fr.Read(tempDate, 4);

if (tempDate[0] = $58) and (tempDate[1] = $69) and (tempDate[2] = $6E) and (tempDate[3] = $67) then
      Result.isVBR := True
    else
      Result.isVBR := False;
    Result.isMp3 := True;
  end
  else
    Result.isMp3 := False; //not MP3 file

fr.Free;
end;

function processFrame(fr: TFileStream; fw: TFileStream; var writeLength: Integer; var writeMillisecond: double): LongInt; //返回:文件位置
var
  binData: array [0..3] of Byte;
  seekDataLength: Integer;
  mpegPadding: Byte;
  mpegVersion: Double;
  mpegLayer: Byte;
  mpegBitrate: Integer;
  mpegSamplingRate : Integer;
  trackMode: Integer;
begin
  fr.Read(binData, 4);
  if (binData[0] = $49) and (binData[1] = $44) and (binData[2] = $33) then
  begin //IDV3
    fr.Seek(2, soFromCurrent);
    fr.Read(binData, 4); //解析长度
    seekDataLength := binData[0] and $7F shl 21 + binData[1] and $7F shl 14 + binData[2] and $7F shl 7 + binData[3] and $7F;
    fr.Seek(seekDataLength, soFromCurrent); //instead of write

writeLength := 0;
    writeMillisecond := 0;
  end
  else
    if binData[0] = $FF then //DATA Frame
    begin

case binData[1] shr 3 and $3 of
      0: mpegVersion := 2.5;
      1: ; //reserved
      2: mpegVersion := 2;
      3: mpegVersion := 1;
      end;

mpegLayer := 4 - (binData[1] shr 1 and $3);

mpegBitrate := mpegBitrateTable[Trunc(mpegVersion)][mpegLayer][binData[2] shr 4 and $F];
      mpegSamplingRate  := samplingRateTable[Trunc(mpegVersion+0.5)][binData[2] shr 2 and $3];
      mpegPadding := binData[2] shr 1 and $1;

seekDataLength := Trunc((samplesPerFrameTable[Trunc(mpegVersion)][mpegLayer] / 8 * mpegBitrate * 1000) / mpegSamplingRate) + mpegPadding;

fr.Seek(32, soFromCurrent); //read Xing(VBR) Flag
      fr.Read(binData, 4);

if (binData[0] = $58) and (binData[1] = $69) and (binData[2] = $6E) and (binData[3] = $67) then
      begin
        fr.Seek(seekDataLength - 4 - 32 - 4, soFromCurrent);
        result := fr.Position;
        writeLength := 0;
        writeMillisecond := 0;
      end
      else //writeData
      begin
        fr.Seek(-32 - 4 - 4, soFromCurrent);
        fw.CopyFrom(fr, seekDataLength); //copy a frame
        writeLength := seekDataLength;
        writeMillisecond := samplesPerFrameTable[Trunc(mpegVersion)][mpegLayer] * 1000.0 / mpegSamplingRate;
        result := fr.Position;
      end;
    end
    else
    begin
      writeLength := 0;
      writeMillisecond := 0;
      result := fr.Position;
    end;
end;

function splitMp3(mode: Mp3SplitMode; length: Integer; fr: TFileStream; writeFileName: string; var actualLength: Integer; var actualMillisecond: Integer): integer;
//length:限制,对于SplitByTime,为毫秒,对于长度,为byte
//actualLength为实际切分长度,actualTime为实际切分毫秒
var
  writeLength: Integer;
  writeMillisecond: double;
  tempMillisecond: double;
  fw: TFileStream;
  total: double;
begin

fw := TFileStream.Create(writeFileName, fmOpenWrite or fmCreate);
  total := 0;
  actualLength := 0;
  tempMillisecond := 0;
  while True do
  begin
    if fr.Position >= fr.Size - 4 then
      break;
    if total >= length then
      break;

result := processFrame(fr, fw, writeLength, writeMillisecond);
    Inc(actualLength, writeLength);
    tempMillisecond := tempMillisecond + writeMillisecond;
    if mode = Mp3SplitByTime then
      total := total + writeMillisecond
    else
      total := total + writeLength;
  end;
  actualMillisecond := Trunc(tempMillisecond);
  fw.Free;
end;

end.

delphi版MP3切割相关推荐

  1. delphi 裁剪mp3_delphi版MP3切割

    好久没写BLOG了,送上一份原创的DELPHI版MP3切割,splitMp3为切割函数,支持按时间切割和按大小切割.望大家支持. 参考VC的资料编写的MP3切割DELPHI版单元. unit Unit ...

  2. delphi 裁剪mp3_delphi版MP3切割 | 学步园

    好久没写BLOG了,送上一份原创的DELPHI版MP3切割,splitMp3为切割函数,支持按时间切割和按大小切割.望大家支持. 参考VC的资料编写的MP3切割DELPHI版单元. unit Unit ...

  3. 通过崩溃地址找错误行数之Delphi版

    通过崩溃地址找错误行数之Delphi版 2009-5-11 17:42:35 来源: 转载 作者:网络 访问:360 次 被顶:2 次 字号:[大 中 小] 核心提示:什么是 MAP 文件?简单地讲, ...

  4. 从内存中加载DLL Delphi版(转)

    源:从内存中加载DLL DELPHI版 原文 : http://www.2ccc.com/article.asp?articleid=5784 MemLibrary.pas //从内存中加载DLL D ...

  5. WinAPI【远程注入】利用远程线程注入DLLDelphi版

    { WinAPI[远程注入]利用远程线程注入DLLDelphi版} (okwary) 小叹的学习园地 ( SDK文档里是这样描述的:进程是一个正在运行的程序,它拥有自己的地址空间,拥有自己的 ...

  6. Delphi 版的IIF函数

    Delphi 版的IIF函数 不少编程语言都有 IIF 函数,我们也可以构造自己的IIF函数: // ------------------------------------------------- ...

  7. NeHe的OpenGL教程7(Bang翻译Delphi版)-如何使用光源

    NeHe的OpenGL教程7(Bang翻译Delphi版)-如何使用光源 在这一课里,我将教会你如何用光源照亮立方体的六个面,如下图: 将下图放在应用程序data目录下,起名NeHe.bmp prog ...

  8. alin的学习之路:嵌入式课程设计总结(基于Linux的Qt版MP3播放器)

    嵌入式课程设计总结(基于Linux的Qt版MP3播放器) 废话不多写直接上图上代码,其中有很多不规范的地方,希望大佬们指正. 1.课设题目 设计一个MP3播放器,要求:使用Linux下的madplay ...

  9. NeHe的OpenGL教程8(Bang翻译Delphi版)-如何制作立体透明效果

    NeHe的OpenGL教程8(Bang翻译Delphi版)-如何制作立体透明效果 在这一课里,我将教会你如何制作立体透明效果,如下图: 将下图放在应用程序data目录下,起名NeHe.bmp prog ...

最新文章

  1. Connecting the Dots: 应用于主动单目深度估计的深度学习模型(CVPR2019)
  2. 计算机视觉/图像处理方向最新论文速递
  3. Java反射机制简单使用
  4. 《python核心编程》读书笔记--第15章 正则表达式
  5. jvm 内存溢出问题排查方法
  6. 每天十分钟系列:JS数据操作之神奇的map()
  7. 微信小程序 禁止弹框下面的内容滑动 弹窗禁止底部内容滚动
  8. usleep延时0.毫秒_【进阶】用swoole实现订单的延时处理(自动取消,还原库存等)...
  9. list copy中status列的状态的意义。
  10. java程序设计教程课后题,一文轻松搞定
  11. jdk自带4种多线程创建方式
  12. pip install -r requirements.txt 超时解决方案
  13. 【事件驱动】【数码管识别】 封装成DLL的函数的梳理
  14. hydra-字典暴力破解
  15. 集成电路制造工艺及设备
  16. C语言编程软件的选择和下载
  17. linux异步io缺陷,具有libaio性能问题的Linux异步IO
  18. Android事件机制深入探讨(一)
  19. html 背景色线性渐变,各种浏览器设置背景颜色线性渐变的方式
  20. html5语音 没反映,【报Bug】关于HTML5 getUserMedia()、audio语音的问题

热门文章

  1. 如何清晰、高质量的给面试官介绍自己的电商项目
  2. 502报错 网络异常
  3. C++的成长之路(02)
  4. 硬件信息获取--DMI
  5. php switch 比较大小,php switch 是松散比较
  6. 【教程】ENVI主成分分析详解
  7. 顶级销售经理的七个特质
  8. 网络入侵检测--Snort软件安装
  9. idea社区版使用(SpringBoot)
  10. 优炫软件连续五年入选“北京软件和信息服务业综合实力前百家企业”