• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ios - 使用 AKSampleDescriptor

[复制链接]
菜鸟教程小白 发表于 2022-12-11 20:45:02 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

使用 AKSamplerDescriptor

我正在使用一个改编的 AKSampler 示例,在该示例中我尝试使用 Fluid.sf3 melodicSounds 的 sforzando 输出。 Sforzando 为每个乐器创建 .sfz 文件,但所有文件都将全局样本指向一个巨大的 .wav 文件。

在所有的instrument.sfz 文件中,对于要使用的波形文件部分,都有一个偏移量和端点描述。

当我加载 .sfz 文件时,由于内存问题,我遇到了崩溃。似乎对于 .sfz 文件中的每个已定义区域,都会再次加载完整的 .wav 文件 (140 mB)。

最有可能的是,在重新加载完整的 .wav 文件时,如 AKSampler 示例中所做的那样使用 AKSampleDescriptor 加载示例文件将忽略偏移量和端点(AKSampleDescriptor.startPoint 和 AKSampleDescriptor.endPoint)。

有没有办法从样本文件中从头到尾加载所需的部分,因为完整的文件包含所有乐器的所有样本数据(我知道并使用当时只提取一种乐器的复音并且工作正常,但这是用于其他用途)

或者,这对我来说似乎是最好的,只需加载一次文件,然后让 sampledescriptors 指向内存中的数据



Best Answer-推荐答案


很好的建议,Rob。我自己也遇到了这个巨大的 WAV 问题,以前从未见过。我也在使用 Sforzando 进行转换。我将考虑向 AKSampler 添加必要的功能。同时,编写一个程序将一个 WAV 文件切割成更小的部分并相应地调整 SFZ 可能会更容易。

这里有一些 Python 2.7 代码来执行此操作,我已成功地将其与 Sforzando 转换的 sf2 soundfont 一起使用。它可能需要更改才能为您工作——sfz 文件之间存在巨大差异——但至少它可能会帮助您入门。此代码需要 PyDub用于处理 WAV 音频的库。

import os
import re
from pydub import AudioSegment

def stripComments(text):
    def replacer(match):
        s = match.group(0)
        if s.startswith('/'):
            return " " # note: a space and not an empty string
        else:
            return s
    pattern = re.compile(
        r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"',
        re.DOTALL | re.MULTILINE
    )
    return re.sub(pattern, replacer, text)

def updateSplitList(splitList, regionLabels, values):
    if len(values) > 3:
        start = int(values['offset'])
        length = int(values['end']) - start
        name = regionLabels.pop(0)
        splitList.add((name, start, length))

def lookupSplitName(splitList, offset, end):
    for (name, start, end) in splitList:
        if offset == start and end == end:
            return name
    return None

def outputGroupAndRegion(outputFile, splitList, values):
    if values.has_key('lokey') and values.has_key('hikey') and values.has_key('pitch_keycenter'):
        outputFile.write('<group> lokey=%s hikey=%s pitch_keycenter=%s\n' % (values['lokey'], values['hikey'], values['pitch_keycenter']))
    elif values.has_key('key') and values.has_key('pitch_keycenter'):
        outputFile.write('<group> key=%s pitch_keycenter=%s\n' % (values['key'], values['pitch_keycenter']))
    if len(values) > 3:
        outputFile.write('    <region> ')
        if values.has_key('lovel') and values.has_key('hivel'):
            outputFile.write('lovel=%s hivel=%s ' % (values['lovel'], values['hivel']))
        if values.has_key('tune'):
            outputFile.write('tune=%s ' % values['tune'])
        if values.has_key('volume'):
            outputFile.write('volume=%s ' % values['volume'])
        if values.has_key('offset'):
            outputFile.write('offset=0 ')
        if values.has_key('end'):
            outputFile.write('end=%d ' % (int(values['end']) - int(values['offset'])))
        if values.has_key('loop_mode'):
            outputFile.write('loop_mode=%s ' % values['loop_mode'])
        if values.has_key('loop_start'):
            outputFile.write('loop_start=%d ' % (int(values['loop_start']) - int(values['offset'])))
        if values.has_key('loop_end'):
            outputFile.write('loop_end=%d ' % (int(values['loop_end']) - int(values['offset'])))
        outputFile.write('sample=samples/%s' % lookupSplitName(splitList, int(values['offset']), int(values['end'])) + '.wav\n')

def process(inputFile, outputFile):

    # create a list of region labels
    regionLabels = list()
    for line in open(inputFile):
        if line.strip().startswith('region_label'):
            regionLabels.append(line.strip().split('=')[1])

    # read entire input SFZ file
    sfz = open(inputFile).read()

    # strip comments and create a mixed list of <header> tags and key=value pairs
    sfz_list = stripComments(sfz).split()

    inSection = "none"
    default_path = ""
    global_sample = None
    values = dict()
    splitList = set()

    # parse the input SFZ data and build up splitList
    for item in sfz_list:
        if item.startswith('<'):
            inSection = item
            updateSplitList(splitList, regionLabels, values)
            values.clear()
            continue
        elif item.find('=') < 0:
            #print 'unknown:', item
            continue

        key, value = item.split('=')
        if inSection == '<control>' and key == 'default_path':
            default_path = value.replace('\\', '/')
        elif inSection == '<global>' and key == 'sample':
            global_sample = value.replace('\\', '/')
        elif inSection == '<region>':
            values[key] = value

    # split the wav file
    bigWav = AudioSegment.from_wav(global_sample)
    #print "%d channels, %d bytes/sample, %d frames/sec" % (bigWav.channels, bigWav.sample_width, bigWav.frame_rate)
    frate = float(bigWav.frame_rate)
    for (name, start, length) in splitList:
        startMs = 1000 * start / frate
        endMs = 1000 * (start + length) / frate
        wav = bigWav[startMs : endMs]
        wavName = 'samples/' + name + '.wav'
        wav.export(wavName, format='wav')

    # parse the input SFZ data again and generate the output SFZ
    for item in sfz_list:
        if item.startswith('<'):
            inSection = item
            outputGroupAndRegion(outputFile, splitList, values)
            values.clear()
            continue
        elif item.find('=') < 0:
            #print 'unknown:', item
            continue

        key, value = item.split('=')
        if inSection == '<control>' and key == 'default_path':
            default_path = value.replace('\\', '/')
        elif inSection == '<global>' and key == 'sample':
            global_sample = value.replace('\\', '/')
        elif inSection == '<region>':
            values[key] = value


dirPath = '000'
fileNameList = os.listdir(dirPath)
for fileName in fileNameList:
    if fileName.endswith('.sfz'):
        inputFile = os.path.join(dirPath, fileName)
        outputFile = open(fileName, 'w')
        print fileName
        process(inputFile, outputFile)

关于ios - 使用 AKSampleDescriptor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53023548/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap